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
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/CMakeLists.txt5
-rw-r--r--source/blender/alembic/intern/abc_exporter.cc5
-rw-r--r--source/blender/alembic/intern/abc_exporter.h3
-rw-r--r--source/blender/alembic/intern/abc_mesh.cc2
-rw-r--r--source/blender/alembic/intern/alembic_capi.cc11
-rw-r--r--source/blender/blenfont/BLF_api.h11
-rw-r--r--source/blender/blenfont/intern/blf.c86
-rw-r--r--source/blender/blenfont/intern/blf_font.c263
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c308
-rw-r--r--source/blender/blenfont/intern/blf_internal.h11
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h67
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h2
-rw-r--r--source/blender/blenkernel/BKE_addon.h13
-rw-r--r--source/blender/blenkernel/BKE_armature.h20
-rw-r--r--source/blender/blenkernel/BKE_blender_undo.h17
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_brush.h5
-rw-r--r--source/blender/blenkernel/BKE_cloth.h3
-rw-r--r--source/blender/blenkernel/BKE_collection.h14
-rw-r--r--source/blender/blenkernel/BKE_context.h6
-rw-r--r--source/blender/blenkernel/BKE_editlattice.h34
-rw-r--r--source/blender/blenkernel/BKE_global.h29
-rw-r--r--source/blender/blenkernel/BKE_group.h6
-rw-r--r--source/blender/blenkernel/BKE_icons.h8
-rw-r--r--source/blender/blenkernel/BKE_image.h5
-rw-r--r--source/blender/blenkernel/BKE_layer.h65
-rw-r--r--source/blender/blenkernel/BKE_main.h6
-rw-r--r--source/blender/blenkernel/BKE_mball.h6
-rw-r--r--source/blender/blenkernel/BKE_mesh.h50
-rw-r--r--source/blender/blenkernel/BKE_modifier.h16
-rw-r--r--source/blender/blenkernel/BKE_movieclip.h1
-rw-r--r--source/blender/blenkernel/BKE_nla.h24
-rw-r--r--source/blender/blenkernel/BKE_node.h10
-rw-r--r--source/blender/blenkernel/BKE_object.h146
-rw-r--r--source/blender/blenkernel/BKE_object_deform.h3
-rw-r--r--source/blender/blenkernel/BKE_paint.h6
-rw-r--r--source/blender/blenkernel/BKE_particle.h49
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h11
-rw-r--r--source/blender/blenkernel/BKE_scene.h19
-rw-r--r--source/blender/blenkernel/BKE_screen.h3
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h8
-rw-r--r--source/blender/blenkernel/BKE_text.h87
-rw-r--r--source/blender/blenkernel/BKE_undo_system.h197
-rw-r--r--source/blender/blenkernel/BKE_workspace.h27
-rw-r--r--source/blender/blenkernel/CMakeLists.txt6
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c23
-rw-r--r--source/blender/blenkernel/intern/addon.c47
-rw-r--r--source/blender/blenkernel/intern/anim.c8
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c47
-rw-r--r--source/blender/blenkernel/intern/armature.c1
-rw-r--r--source/blender/blenkernel/intern/armature_update.c114
-rw-r--r--source/blender/blenkernel/intern/blender.c13
-rw-r--r--source/blender/blenkernel/intern/blender_undo.c315
-rw-r--r--source/blender/blenkernel/intern/boids.c2
-rw-r--r--source/blender/blenkernel/intern/bpath.c4
-rw-r--r--source/blender/blenkernel/intern/brush.c4
-rw-r--r--source/blender/blenkernel/intern/bullet.c2
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c12
-rw-r--r--source/blender/blenkernel/intern/cachefile.c2
-rw-r--r--source/blender/blenkernel/intern/camera.c5
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c4
-rw-r--r--source/blender/blenkernel/intern/cloth.c6
-rw-r--r--source/blender/blenkernel/intern/collection.c238
-rw-r--r--source/blender/blenkernel/intern/collision.c22
-rw-r--r--source/blender/blenkernel/intern/colorband.c2
-rw-r--r--source/blender/blenkernel/intern/constraint.c7
-rw-r--r--source/blender/blenkernel/intern/context.c24
-rw-r--r--source/blender/blenkernel/intern/curve.c4
-rw-r--r--source/blender/blenkernel/intern/curve_decimate.c2
-rw-r--r--source/blender/blenkernel/intern/displist.c5
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c16
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c2
-rw-r--r--source/blender/blenkernel/intern/editlattice.c147
-rw-r--r--source/blender/blenkernel/intern/effect.c5
-rw-r--r--source/blender/blenkernel/intern/fcurve.c10
-rw-r--r--source/blender/blenkernel/intern/fluidsim.c5
-rw-r--r--source/blender/blenkernel/intern/font.c9
-rw-r--r--source/blender/blenkernel/intern/group.c42
-rw-r--r--source/blender/blenkernel/intern/icons.c27
-rw-r--r--source/blender/blenkernel/intern/idprop.c5
-rw-r--r--source/blender/blenkernel/intern/image.c214
-rw-r--r--source/blender/blenkernel/intern/ipo.c2
-rw-r--r--source/blender/blenkernel/intern/lamp.c1
-rw-r--r--source/blender/blenkernel/intern/lattice.c1
-rw-r--r--source/blender/blenkernel/intern/layer.c354
-rw-r--r--source/blender/blenkernel/intern/library.c5
-rw-r--r--source/blender/blenkernel/intern/library_query.c15
-rw-r--r--source/blender/blenkernel/intern/library_remap.c33
-rw-r--r--source/blender/blenkernel/intern/linestyle.c1
-rw-r--r--source/blender/blenkernel/intern/mask.c2
-rw-r--r--source/blender/blenkernel/intern/mask_evaluate.c8
-rw-r--r--source/blender/blenkernel/intern/material.c19
-rw-r--r--source/blender/blenkernel/intern/mball.c6
-rw-r--r--source/blender/blenkernel/intern/mesh.c32
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c323
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c20
-rw-r--r--source/blender/blenkernel/intern/modifier.c30
-rw-r--r--source/blender/blenkernel/intern/modifiers_bmesh.c20
-rw-r--r--source/blender/blenkernel/intern/movieclip.c43
-rw-r--r--source/blender/blenkernel/intern/nla.c85
-rw-r--r--source/blender/blenkernel/intern/node.c11
-rw-r--r--source/blender/blenkernel/intern/object.c53
-rw-r--r--source/blender/blenkernel/intern/object_deform.c70
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c23
-rw-r--r--source/blender/blenkernel/intern/object_update.c36
-rw-r--r--source/blender/blenkernel/intern/ocean.c8
-rw-r--r--source/blender/blenkernel/intern/outliner_treehash.c4
-rw-r--r--source/blender/blenkernel/intern/packedFile.c11
-rw-r--r--source/blender/blenkernel/intern/paint.c47
-rw-r--r--source/blender/blenkernel/intern/particle.c327
-rw-r--r--source/blender/blenkernel/intern/particle_child.c330
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c291
-rw-r--r--source/blender/blenkernel/intern/particle_system.c96
-rw-r--r--source/blender/blenkernel/intern/pbvh.c6
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c36
-rw-r--r--source/blender/blenkernel/intern/pointcache.c107
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c122
-rw-r--r--source/blender/blenkernel/intern/scene.c250
-rw-r--r--source/blender/blenkernel/intern/screen.c27
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c1
-rw-r--r--source/blender/blenkernel/intern/sequencer.c75
-rw-r--r--source/blender/blenkernel/intern/smoke.c13
-rw-r--r--source/blender/blenkernel/intern/softbody.c12
-rw-r--r--source/blender/blenkernel/intern/speaker.c1
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c10
-rw-r--r--source/blender/blenkernel/intern/text.c660
-rw-r--r--source/blender/blenkernel/intern/texture.c12
-rw-r--r--source/blender/blenkernel/intern/tracking_region_tracker.c2
-rw-r--r--source/blender/blenkernel/intern/tracking_util.c4
-rw-r--r--source/blender/blenkernel/intern/undo_system.c846
-rw-r--r--source/blender/blenkernel/intern/workspace.c48
-rw-r--r--source/blender/blenkernel/intern/world.c3
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c59
-rw-r--r--source/blender/blenkernel/particle_private.h54
-rw-r--r--source/blender/blenlib/BLI_array.h51
-rw-r--r--source/blender/blenlib/BLI_array_utils.h12
-rw-r--r--source/blender/blenlib/BLI_assert.h106
-rw-r--r--source/blender/blenlib/BLI_boxpack_2d.h (renamed from source/blender/blenlib/BLI_boxpack2d.h)10
-rw-r--r--source/blender/blenlib/BLI_buffer.h2
-rw-r--r--source/blender/blenlib/BLI_console.h42
-rw-r--r--source/blender/blenlib/BLI_convexhull_2d.h (renamed from source/blender/blenlib/BLI_convexhull2d.h)8
-rw-r--r--source/blender/blenlib/BLI_dial_2d.h (renamed from source/blender/blenlib/BLI_dial.h)8
-rw-r--r--source/blender/blenlib/BLI_edgehash.h4
-rw-r--r--source/blender/blenlib/BLI_fileops.h1
-rw-r--r--source/blender/blenlib/BLI_ghash.h249
-rw-r--r--source/blender/blenlib/BLI_gsqueue.h4
-rw-r--r--source/blender/blenlib/BLI_hash.h17
-rw-r--r--source/blender/blenlib/BLI_heap.h4
-rw-r--r--source/blender/blenlib/BLI_iterator.h2
-rw-r--r--source/blender/blenlib/BLI_jitter_2d.h (renamed from source/blender/blenlib/BLI_jitter.h)8
-rw-r--r--source/blender/blenlib/BLI_kdopbvh.h2
-rw-r--r--source/blender/blenlib/BLI_lasso_2d.h (renamed from source/blender/blenlib/BLI_lasso.h)8
-rw-r--r--source/blender/blenlib/BLI_link_utils.h12
-rw-r--r--source/blender/blenlib/BLI_linklist_stack.h2
-rw-r--r--source/blender/blenlib/BLI_listbase.h17
-rw-r--r--source/blender/blenlib/BLI_math_base.h5
-rw-r--r--source/blender/blenlib/BLI_math_geom.h1
-rw-r--r--source/blender/blenlib/BLI_mempool.h2
-rw-r--r--source/blender/blenlib/BLI_polyfill_2d.h (renamed from source/blender/blenlib/BLI_polyfill2d.h)6
-rw-r--r--source/blender/blenlib/BLI_polyfill_2d_beautify.h (renamed from source/blender/blenlib/BLI_polyfill2d_beautify.h)6
-rw-r--r--source/blender/blenlib/BLI_smallhash.h2
-rw-r--r--source/blender/blenlib/BLI_sort_utils.h7
-rw-r--r--source/blender/blenlib/BLI_string.h14
-rw-r--r--source/blender/blenlib/BLI_string_utf8.h10
-rw-r--r--source/blender/blenlib/BLI_threads.h24
-rw-r--r--source/blender/blenlib/BLI_utildefines.h75
-rw-r--r--source/blender/blenlib/BLI_voronoi_2d.h (renamed from source/blender/blenlib/BLI_voronoi.h)8
-rw-r--r--source/blender/blenlib/CMakeLists.txt34
-rw-r--r--source/blender/blenlib/intern/BLI_array.c20
-rw-r--r--source/blender/blenlib/intern/BLI_dial_2d.c (renamed from source/blender/blenlib/intern/BLI_dial.c)6
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c269
-rw-r--r--source/blender/blenlib/intern/BLI_ghash_utils.c288
-rw-r--r--source/blender/blenlib/intern/BLI_heap.c6
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c6
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c2
-rw-r--r--source/blender/blenlib/intern/array_store.c15
-rw-r--r--source/blender/blenlib/intern/array_utils.c17
-rw-r--r--source/blender/blenlib/intern/astar.c2
-rw-r--r--source/blender/blenlib/intern/boxpack_2d.c (renamed from source/blender/blenlib/intern/boxpack2d.c)4
-rw-r--r--source/blender/blenlib/intern/convexhull_2d.c (renamed from source/blender/blenlib/intern/convexhull2d.c)4
-rw-r--r--source/blender/blenlib/intern/edgehash.c10
-rw-r--r--source/blender/blenlib/intern/gsqueue.c4
-rw-r--r--source/blender/blenlib/intern/jitter_2d.c (renamed from source/blender/blenlib/intern/jitter.c)4
-rw-r--r--source/blender/blenlib/intern/lasso_2d.c (renamed from source/blender/blenlib/intern/lasso.c)4
-rw-r--r--source/blender/blenlib/intern/listbase.c2
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c25
-rw-r--r--source/blender/blenlib/intern/math_bits_inline.c4
-rw-r--r--source/blender/blenlib/intern/math_color.c185
-rw-r--r--source/blender/blenlib/intern/math_geom.c16
-rw-r--r--source/blender/blenlib/intern/math_vector.c2
-rw-r--r--source/blender/blenlib/intern/polyfill_2d.c (renamed from source/blender/blenlib/intern/polyfill2d.c)4
-rw-r--r--source/blender/blenlib/intern/polyfill_2d_beautify.c (renamed from source/blender/blenlib/intern/polyfill2d_beautify.c)11
-rw-r--r--source/blender/blenlib/intern/rand.c6
-rw-r--r--source/blender/blenlib/intern/smallhash.c2
-rw-r--r--source/blender/blenlib/intern/sort_utils.c22
-rw-r--r--source/blender/blenlib/intern/storage.c2
-rw-r--r--source/blender/blenlib/intern/string.c8
-rw-r--r--source/blender/blenlib/intern/task.c16
-rw-r--r--source/blender/blenlib/intern/threads.c34
-rw-r--r--source/blender/blenlib/intern/voronoi_2d.c (renamed from source/blender/blenlib/intern/voronoi.c)10
-rw-r--r--source/blender/blenloader/BLO_readfile.h2
-rw-r--r--source/blender/blenloader/BLO_undofile.h29
-rw-r--r--source/blender/blenloader/intern/readfile.c150
-rw-r--r--source/blender/blenloader/intern/undofile.c132
-rw-r--r--source/blender/blenloader/intern/versioning_250.c2
-rw-r--r--source/blender/blenloader/intern/versioning_260.c2
-rw-r--r--source/blender/blenloader/intern/versioning_270.c37
-rw-r--r--source/blender/blenloader/intern/versioning_280.c30
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c2
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c9
-rw-r--r--source/blender/blenloader/intern/writefile.c245
-rw-r--r--source/blender/blentranslation/msgfmt/msgfmt.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c19
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_log.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c77
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h5
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.c8
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.h3
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c14
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c1
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c15
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon_edgenet.c8
-rw-r--r--source/blender/bmesh/intern/bmesh_private.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c22
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h20
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.c10
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.h4
-rw-r--r--source/blender/bmesh/operators/bmo_connect_concave.c4
-rw-r--r--source/blender/bmesh/operators/bmo_connect_pair.c4
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c8
-rw-r--r--source/blender/bmesh/operators/bmo_edgenet.c30
-rw-r--r--source/blender/bmesh/operators/bmo_face_island.c2
-rw-r--r--source/blender/bmesh/operators/bmo_hull.c2
-rw-r--r--source/blender/bmesh/operators/bmo_join_triangles.c2
-rw-r--r--source/blender/bmesh/operators/bmo_mesh_conv.c11
-rw-r--r--source/blender/bmesh/operators/bmo_rotate_edges.c2
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide.c16
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide_edgering.c4
-rw-r--r--source/blender/bmesh/operators/bmo_triangulate.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.c4
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c804
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_collapse.c8
-rw-r--r--source/blender/bmesh/tools/bmesh_edgenet.c4
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.c6
-rw-r--r--source/blender/bmesh/tools/bmesh_path.c6
-rw-r--r--source/blender/bmesh/tools/bmesh_region_match.c14
-rw-r--r--source/blender/bmesh/tools/bmesh_separate.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_triangulate.c4
-rw-r--r--source/blender/collada/AnimationExporter.cpp649
-rw-r--r--source/blender/collada/AnimationExporter.h37
-rw-r--r--source/blender/collada/AnimationImporter.cpp134
-rw-r--r--source/blender/collada/AnimationImporter.h9
-rw-r--r--source/blender/collada/ArmatureExporter.cpp6
-rw-r--r--source/blender/collada/ArmatureImporter.cpp11
-rw-r--r--source/blender/collada/ControllerExporter.cpp6
-rw-r--r--source/blender/collada/DocumentExporter.cpp34
-rw-r--r--source/blender/collada/DocumentExporter.h9
-rw-r--r--source/blender/collada/DocumentImporter.cpp23
-rw-r--r--source/blender/collada/EffectExporter.cpp4
-rw-r--r--source/blender/collada/ErrorHandler.cpp15
-rw-r--r--source/blender/collada/ExportSettings.h29
-rw-r--r--source/blender/collada/ImageExporter.cpp4
-rw-r--r--source/blender/collada/ImportSettings.h7
-rw-r--r--source/blender/collada/MeshImporter.cpp10
-rw-r--r--source/blender/collada/SceneExporter.cpp11
-rw-r--r--source/blender/collada/SceneExporter.h5
-rw-r--r--source/blender/collada/collada.cpp102
-rw-r--r--source/blender/collada/collada.h49
-rw-r--r--source/blender/collada/collada_internal.cpp6
-rw-r--r--source/blender/collada/collada_internal.h4
-rw-r--r--source/blender/collada/collada_utils.cpp242
-rw-r--r--source/blender/collada/collada_utils.h14
-rw-r--r--source/blender/compositor/CMakeLists.txt1
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.cpp12
-rw-r--r--source/blender/compositor/nodes/COM_ImageNode.cpp2
-rw-r--r--source/blender/compositor/operations/COM_CompositorOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_KeyingScreenOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_MapRangeOperation.cpp5
-rw-r--r--source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.h12
-rw-r--r--source/blender/compositor/operations/COM_VectorBlurOperation.cpp716
-rw-r--r--source/blender/compositor/operations/COM_ViewerOperation.cpp6
-rw-r--r--source/blender/depsgraph/CMakeLists.txt4
-rw-r--r--source/blender/depsgraph/DEG_depsgraph.h58
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_query.h44
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cycle.cc93
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_map.cc (renamed from source/blender/modifiers/intern/MOD_boolean_util.h)50
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_map.h69
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc455
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h57
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc126
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc92
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc57
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc460
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h47
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc124
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc59
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc12
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_transitive.cc2
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc6
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc178
-rw-r--r--source/blender/depsgraph/intern/depsgraph.h14
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc103
-rw-r--r--source/blender/depsgraph/intern/depsgraph_debug.cc5
-rw-r--r--source/blender/depsgraph/intern/depsgraph_eval.cc58
-rw-r--r--source/blender/depsgraph/intern/depsgraph_intern.h15
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query.cc56
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_iter.cc20
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc115
-rw-r--r--source/blender/depsgraph/intern/depsgraph_type_defines.cc6
-rw-r--r--source/blender/depsgraph/intern/depsgraph_types.h8
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.cc28
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.h3
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc357
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc45
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.cc8
-rw-r--r--source/blender/depsgraph/util/deg_util_function.h2
-rw-r--r--source/blender/draw/CMakeLists.txt14
-rw-r--r--source/blender/draw/DRW_engine.h24
-rw-r--r--source/blender/draw/engines/basic/basic_engine.c59
-rw-r--r--source/blender/draw/engines/clay/clay_engine.c529
-rw-r--r--source/blender/draw/engines/clay/shaders/clay_copy.glsl10
-rw-r--r--source/blender/draw/engines/clay/shaders/clay_frag.glsl81
-rw-r--r--source/blender/draw/engines/clay/shaders/clay_fxaa.glsl18
-rw-r--r--source/blender/draw/engines/clay/shaders/clay_prepass_frag.glsl44
-rw-r--r--source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl6
-rw-r--r--source/blender/draw/engines/eevee/eevee_bloom.c95
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c103
-rw-r--r--source/blender/draw/engines/eevee/eevee_depth_of_field.c120
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c217
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c221
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c670
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c381
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c376
-rw-r--r--source/blender/draw/engines/eevee/eevee_mist.c139
-rw-r--r--source/blender/draw/engines/eevee/eevee_motion_blur.c50
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c129
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h208
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c562
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c114
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c254
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c154
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c155
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl176
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl9
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl31
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl18
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl1
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_vert.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl6
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl5
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_vert.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl145
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_vert.glsl4
-rw-r--r--source/blender/draw/engines/external/external_engine.c1
-rw-r--r--source/blender/draw/intern/DRW_render.h169
-rw-r--r--source/blender/draw/intern/draw_armature.c4
-rw-r--r--source/blender/draw/intern/draw_cache.c118
-rw-r--r--source/blender/draw/intern/draw_cache.h5
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h2
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c59
-rw-r--r--source/blender/draw/intern/draw_cache_impl_particles.c494
-rw-r--r--source/blender/draw/intern/draw_common.c187
-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.c249
-rw-r--r--source/blender/draw/intern/draw_instance_data.h19
-rw-r--r--source/blender/draw/intern/draw_manager.c3236
-rw-r--r--source/blender/draw/intern/draw_manager.h358
-rw-r--r--source/blender/draw/intern/draw_manager_data.c935
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c1170
-rw-r--r--source/blender/draw/intern/draw_manager_profiling.c135
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c387
-rw-r--r--source/blender/draw/intern/draw_manager_texture.c237
-rw-r--r--source/blender/draw/intern/draw_view.c73
-rw-r--r--source/blender/draw/modes/edit_armature_mode.c1
-rw-r--r--source/blender/draw/modes/edit_curve_mode.c4
-rw-r--r--source/blender/draw/modes/edit_groom_mode.c2
-rw-r--r--source/blender/draw/modes/edit_lattice_mode.c5
-rw-r--r--source/blender/draw/modes/edit_mesh_mode.c49
-rw-r--r--source/blender/draw/modes/edit_metaball_mode.c17
-rw-r--r--source/blender/draw/modes/edit_surface_mode.c1
-rw-r--r--source/blender/draw/modes/edit_text_mode.c5
-rw-r--r--source/blender/draw/modes/object_mode.c322
-rw-r--r--source/blender/draw/modes/paint_texture_mode.c1
-rw-r--r--source/blender/draw/modes/paint_vertex_mode.c1
-rw-r--r--source/blender/draw/modes/paint_weight_mode.c1
-rw-r--r--source/blender/draw/modes/particle_mode.c5
-rw-r--r--source/blender/draw/modes/pose_mode.c9
-rw-r--r--source/blender/draw/modes/sculpt_mode.c7
-rw-r--r--source/blender/draw/modes/shaders/common_fullscreen_vert.glsl (renamed from source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl)0
-rw-r--r--source/blender/draw/modes/shaders/common_view_lib.glsl14
-rw-r--r--source/blender/draw/modes/shaders/object_particle_prim_frag.glsl9
-rw-r--r--source/blender/editors/CMakeLists.txt2
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c2
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c65
-rw-r--r--source/blender/editors/animation/anim_draw.c2
-rw-r--r--source/blender/editors/animation/anim_filter.c74
-rw-r--r--source/blender/editors/animation/anim_markers.c9
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c2
-rw-r--r--source/blender/editors/animation/keyframes_edit.c2
-rw-r--r--source/blender/editors/animation/keyframing.c4
-rw-r--r--source/blender/editors/armature/CMakeLists.txt1
-rw-r--r--source/blender/editors/armature/armature_add.c26
-rw-r--r--source/blender/editors/armature/armature_edit.c20
-rw-r--r--source/blender/editors/armature/armature_intern.h2
-rw-r--r--source/blender/editors/armature/armature_naming.c17
-rw-r--r--source/blender/editors/armature/armature_relations.c40
-rw-r--r--source/blender/editors/armature/armature_select.c13
-rw-r--r--source/blender/editors/armature/armature_skinning.c35
-rw-r--r--source/blender/editors/armature/armature_utils.c94
-rw-r--r--source/blender/editors/armature/editarmature_retarget.c2
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c12
-rw-r--r--source/blender/editors/armature/editarmature_undo.c192
-rw-r--r--source/blender/editors/armature/meshlaplacian.c9
-rw-r--r--source/blender/editors/armature/meshlaplacian.h9
-rw-r--r--source/blender/editors/armature/pose_edit.c68
-rw-r--r--source/blender/editors/armature/pose_lib.c34
-rw-r--r--source/blender/editors/armature/pose_select.c10
-rw-r--r--source/blender/editors/armature/pose_transform.c24
-rw-r--r--source/blender/editors/armature/reeb.c10
-rw-r--r--source/blender/editors/curve/CMakeLists.txt1
-rw-r--r--source/blender/editors/curve/curve_intern.h5
-rw-r--r--source/blender/editors/curve/editcurve.c141
-rw-r--r--source/blender/editors/curve/editcurve_add.c2
-rw-r--r--source/blender/editors/curve/editcurve_paint.c16
-rw-r--r--source/blender/editors/curve/editcurve_select.c6
-rw-r--r--source/blender/editors/curve/editcurve_undo.c257
-rw-r--r--source/blender/editors/curve/editfont.c2
-rw-r--r--source/blender/editors/curve/editfont_undo.c123
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_brush.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c5
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c3
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_undo.c1
-rw-r--r--source/blender/editors/groom/editgroom_select.c2
-rw-r--r--source/blender/editors/include/BIF_glutil.h32
-rw-r--r--source/blender/editors/include/ED_armature.h28
-rw-r--r--source/blender/editors/include/ED_curve.h10
-rw-r--r--source/blender/editors/include/ED_image.h2
-rw-r--r--source/blender/editors/include/ED_lattice.h18
-rw-r--r--source/blender/editors/include/ED_mball.h4
-rw-r--r--source/blender/editors/include/ED_mesh.h22
-rw-r--r--source/blender/editors/include/ED_object.h79
-rw-r--r--source/blender/editors/include/ED_paint.h39
-rw-r--r--source/blender/editors/include/ED_particle.h15
-rw-r--r--source/blender/editors/include/ED_scene.h7
-rw-r--r--source/blender/editors/include/ED_screen.h14
-rw-r--r--source/blender/editors/include/ED_sculpt.h6
-rw-r--r--source/blender/editors/include/ED_text.h10
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h5
-rw-r--r--source/blender/editors/include/ED_undo.h64
-rw-r--r--source/blender/editors/include/ED_util.h39
-rw-r--r--source/blender/editors/include/ED_uvedit.h89
-rw-r--r--source/blender/editors/include/ED_view3d.h22
-rw-r--r--source/blender/editors/include/UI_interface.h6
-rw-r--r--source/blender/editors/include/UI_interface_icons.h3
-rw-r--r--source/blender/editors/interface/CMakeLists.txt6
-rw-r--r--source/blender/editors/interface/interface.c46
-rw-r--r--source/blender/editors/interface/interface_draw.c160
-rw-r--r--source/blender/editors/interface/interface_handlers.c51
-rw-r--r--source/blender/editors/interface/interface_icons.c162
-rw-r--r--source/blender/editors/interface/interface_intern.h29
-rw-r--r--source/blender/editors/interface/interface_layout.c2
-rw-r--r--source/blender/editors/interface/interface_ops.c13
-rw-r--r--source/blender/editors/interface/interface_panel.c74
-rw-r--r--source/blender/editors/interface/interface_region_menu_pie.c3
-rw-r--r--source/blender/editors/interface/interface_region_menu_popup.c3
-rw-r--r--source/blender/editors/interface/interface_region_popup.c22
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c10
-rw-r--r--source/blender/editors/interface/interface_templates.c8
-rw-r--r--source/blender/editors/interface/interface_widgets.c653
-rw-r--r--source/blender/editors/interface/resources.c18
-rw-r--r--source/blender/editors/interface/view2d.c21
-rw-r--r--source/blender/editors/io/io_alembic.c8
-rw-r--r--source/blender/editors/io/io_cache.c1
-rw-r--r--source/blender/editors/io/io_collada.c124
-rw-r--r--source/blender/editors/lattice/CMakeLists.txt46
-rw-r--r--source/blender/editors/lattice/editlattice_select.c (renamed from source/blender/editors/object/object_lattice.c)514
-rw-r--r--source/blender/editors/lattice/editlattice_tools.c341
-rw-r--r--source/blender/editors/lattice/editlattice_undo.c196
-rw-r--r--source/blender/editors/lattice/lattice_intern.h44
-rw-r--r--source/blender/editors/lattice/lattice_ops.c80
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c2
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c2
-rw-r--r--source/blender/editors/mask/mask_draw.c2
-rw-r--r--source/blender/editors/mask/mask_select.c2
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt1
-rw-r--r--source/blender/editors/mesh/editface.c257
-rw-r--r--source/blender/editors/mesh/editmesh_add.c7
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c5
-rw-r--r--source/blender/editors/mesh/editmesh_bisect.c2
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c123
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c7
-rw-r--r--source/blender/editors/mesh/editmesh_intersect.c2
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c12
-rw-r--r--source/blender/editors/mesh/editmesh_path.c66
-rw-r--r--source/blender/editors/mesh/editmesh_select.c480
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c745
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c137
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c389
-rw-r--r--source/blender/editors/mesh/mesh_data.c31
-rw-r--r--source/blender/editors/mesh/mesh_mirror.c377
-rw-r--r--source/blender/editors/mesh/meshtools.c142
-rw-r--r--source/blender/editors/metaball/CMakeLists.txt1
-rw-r--r--source/blender/editors/metaball/editmball_undo.c200
-rw-r--r--source/blender/editors/metaball/mball_edit.c95
-rw-r--r--source/blender/editors/object/CMakeLists.txt2
-rw-r--r--source/blender/editors/object/object_add.c36
-rw-r--r--source/blender/editors/object/object_bake.c14
-rw-r--r--source/blender/editors/object/object_bake_api.c42
-rw-r--r--source/blender/editors/object/object_constraint.c22
-rw-r--r--source/blender/editors/object/object_edit.c536
-rw-r--r--source/blender/editors/object/object_facemap_ops.c8
-rw-r--r--source/blender/editors/object/object_hook.c2
-rw-r--r--source/blender/editors/object/object_intern.h13
-rw-r--r--source/blender/editors/object/object_modes.c258
-rw-r--r--source/blender/editors/object/object_modifier.c69
-rw-r--r--source/blender/editors/object/object_ops.c38
-rw-r--r--source/blender/editors/object/object_relations.c95
-rw-r--r--source/blender/editors/object/object_select.c110
-rw-r--r--source/blender/editors/object/object_transform.c8
-rw-r--r--source/blender/editors/object/object_vgroup.c188
-rw-r--r--source/blender/editors/physics/CMakeLists.txt2
-rw-r--r--source/blender/editors/physics/dynamicpaint_ops.c11
-rw-r--r--source/blender/editors/physics/particle_edit.c503
-rw-r--r--source/blender/editors/physics/particle_edit_undo.c301
-rw-r--r--source/blender/editors/physics/particle_edit_utildefines.h50
-rw-r--r--source/blender/editors/physics/particle_object.c71
-rw-r--r--source/blender/editors/physics/physics_fluid.c10
-rw-r--r--source/blender/editors/physics/physics_intern.h14
-rw-r--r--source/blender/editors/physics/physics_pointcache.c58
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c1
-rw-r--r--source/blender/editors/physics/rigidbody_object.c1
-rw-r--r--source/blender/editors/render/render_internal.c65
-rw-r--r--source/blender/editors/render/render_opengl.c48
-rw-r--r--source/blender/editors/render/render_preview.c27
-rw-r--r--source/blender/editors/render/render_update.c40
-rw-r--r--source/blender/editors/scene/scene_edit.c33
-rw-r--r--source/blender/editors/screen/CMakeLists.txt1
-rw-r--r--source/blender/editors/screen/area.c124
-rw-r--r--source/blender/editors/screen/glutil.c137
-rw-r--r--source/blender/editors/screen/screen_context.c24
-rw-r--r--source/blender/editors/screen/screen_draw.c9
-rw-r--r--source/blender/editors/screen/screen_edit.c90
-rw-r--r--source/blender/editors/screen/screen_intern.h2
-rw-r--r--source/blender/editors/screen/screen_ops.c64
-rw-r--r--source/blender/editors/screen/workspace_edit.c100
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt3
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve.c112
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve_undo.c168
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c376
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c36
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_undo.c535
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h55
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c10
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_undo.c410
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c272
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_proj.c17
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c6
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c423
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h21
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c186
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c8
-rw-r--r--source/blender/editors/sound/sound_ops.c5
-rw-r--r--source/blender/editors/space_action/action_buttons.c2
-rw-r--r--source/blender/editors/space_action/action_data.c6
-rw-r--r--source/blender/editors/space_action/action_edit.c1
-rw-r--r--source/blender/editors/space_action/action_select.c12
-rw-r--r--source/blender/editors/space_api/spacetypes.c5
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c2
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c20
-rw-r--r--source/blender/editors/space_clip/clip_draw.c9
-rw-r--r--source/blender/editors/space_clip/clip_toolbar.c2
-rw-r--r--source/blender/editors/space_clip/clip_utils.c2
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c2
-rw-r--r--source/blender/editors/space_clip/tracking_ops_orient.c5
-rw-r--r--source/blender/editors/space_clip/tracking_select.c2
-rw-r--r--source/blender/editors/space_file/file_draw.c10
-rw-r--r--source/blender/editors/space_file/space_file.c18
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c2
-rw-r--r--source/blender/editors/space_graph/graph_draw.c37
-rw-r--r--source/blender/editors/space_graph/graph_edit.c2
-rw-r--r--source/blender/editors/space_graph/graph_select.c2
-rw-r--r--source/blender/editors/space_graph/graph_utils.c4
-rw-r--r--source/blender/editors/space_graph/space_graph.c15
-rw-r--r--source/blender/editors/space_image/image_buttons.c2
-rw-r--r--source/blender/editors/space_image/image_draw.c14
-rw-r--r--source/blender/editors/space_image/image_edit.c6
-rw-r--r--source/blender/editors/space_image/image_ops.c17
-rw-r--r--source/blender/editors/space_image/space_image.c4
-rw-r--r--source/blender/editors/space_info/info_report.c3
-rw-r--r--source/blender/editors/space_info/info_stats.c44
-rw-r--r--source/blender/editors/space_info/textview.c2
-rw-r--r--source/blender/editors/space_logic/logic_window.c2
-rw-r--r--source/blender/editors/space_nla/nla_channels.c8
-rw-r--r--source/blender/editors/space_nla/nla_draw.c28
-rw-r--r--source/blender/editors/space_nla/nla_edit.c24
-rw-r--r--source/blender/editors/space_nla/space_nla.c15
-rw-r--r--source/blender/editors/space_node/drawnode.c385
-rw-r--r--source/blender/editors/space_node/node_draw.c21
-rw-r--r--source/blender/editors/space_node/node_intern.h5
-rw-r--r--source/blender/editors/space_node/node_select.c2
-rw-r--r--source/blender/editors/space_node/node_templates.c6
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c301
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c59
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c1
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h19
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c4
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c57
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c89
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c18
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c24
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c61
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c7
-rw-r--r--source/blender/editors/space_text/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c13
-rw-r--r--source/blender/editors/space_text/text_draw.c2
-rw-r--r--source/blender/editors/space_text/text_format_pov.c84
-rw-r--r--source/blender/editors/space_text/text_ops.c145
-rw-r--r--source/blender/editors/space_text/text_undo.c185
-rw-r--r--source/blender/editors/space_time/space_time.c2
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c2
-rw-r--r--source/blender/editors/space_view3d/drawobject.c92
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c43
-rw-r--r--source/blender/editors/space_view3d/view3d_camera_control.c6
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c144
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c121
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c703
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c20
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h10
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_camera.c21
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_forcefield.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_navigate.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_ruler.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c151
-rw-r--r--source/blender/editors/space_view3d/view3d_toolbar.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c105
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c6
-rw-r--r--source/blender/editors/transform/transform.c25
-rw-r--r--source/blender/editors/transform/transform.h8
-rw-r--r--source/blender/editors/transform/transform_constraints.c2
-rw-r--r--source/blender/editors/transform/transform_conversions.c182
-rw-r--r--source/blender/editors/transform/transform_generics.c22
-rw-r--r--source/blender/editors/transform/transform_manipulator.c6
-rw-r--r--source/blender/editors/transform/transform_manipulator2d.c6
-rw-r--r--source/blender/editors/transform/transform_ops.c3
-rw-r--r--source/blender/editors/transform/transform_orientations.c2
-rw-r--r--source/blender/editors/transform/transform_snap.c5
-rw-r--r--source/blender/editors/transform/transform_snap_object.c39
-rw-r--r--source/blender/editors/undo/CMakeLists.txt45
-rw-r--r--source/blender/editors/undo/ed_undo.c (renamed from source/blender/editors/util/undo.c)422
-rw-r--r--source/blender/editors/undo/memfile_undo.c151
-rw-r--r--source/blender/editors/undo/undo_intern.h (renamed from source/blender/editors/util/util_intern.h)27
-rw-r--r--source/blender/editors/undo/undo_system_types.c74
-rw-r--r--source/blender/editors/util/CMakeLists.txt4
-rw-r--r--source/blender/editors/util/ed_util.c116
-rw-r--r--source/blender/editors/util/editmode_undo.c361
-rw-r--r--source/blender/editors/util/numinput.c7
-rw-r--r--source/blender/editors/uvedit/uvedit_buttons.c14
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c293
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h27
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c736
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c10
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c19
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp361
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h14
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp52
-rw-r--r--source/blender/gpu/CMakeLists.txt29
-rw-r--r--source/blender/gpu/GPU_batch.h6
-rw-r--r--source/blender/gpu/GPU_compositing.h106
-rw-r--r--source/blender/gpu/GPU_draw.h9
-rw-r--r--source/blender/gpu/GPU_extensions.h1
-rw-r--r--source/blender/gpu/GPU_framebuffer.h147
-rw-r--r--source/blender/gpu/GPU_material.h22
-rw-r--r--source/blender/gpu/GPU_select.h1
-rw-r--r--source/blender/gpu/GPU_shader.h19
-rw-r--r--source/blender/gpu/GPU_texture.h12
-rw-r--r--source/blender/gpu/GPU_viewport.h16
-rw-r--r--source/blender/gpu/intern/gpu_batch.c2
-rw-r--r--source/blender/gpu/intern/gpu_batch_presets.c74
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c140
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c268
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h25
-rw-r--r--source/blender/gpu/intern/gpu_compositing.c1494
-rw-r--r--source/blender/gpu/intern/gpu_draw.c128
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c10
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c938
-rw-r--r--source/blender/gpu/intern/gpu_lamp.c115
-rw-r--r--source/blender/gpu/intern/gpu_material.c85
-rw-r--r--source/blender/gpu/intern/gpu_select.c12
-rw-r--r--source/blender/gpu/intern/gpu_select_pick.c112
-rw-r--r--source/blender/gpu/intern/gpu_select_sample_query.c40
-rw-r--r--source/blender/gpu/intern/gpu_shader.c196
-rw-r--r--source/blender/gpu/intern/gpu_shader_private.h3
-rw-r--r--source/blender/gpu/intern/gpu_texture.c295
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c406
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl48
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl35
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_nodelink_frag.glsl10
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl107
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl35
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl186
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl64
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_frag.glsl (renamed from source/blender/gpu/shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl)4
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl4
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl11
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_mball_handles_vert.glsl (renamed from source/blender/gpu/shaders/gpu_shader_instance_mball_helpers_vert.glsl)0
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl205
-rw-r--r--source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_frag.glsl61
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_geom.glsl37
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl36
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_simple_vert.glsl22
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_vert.glsl19
-rw-r--r--source/blender/ikplugin/intern/itasc_plugin.cpp24
-rw-r--r--source/blender/imbuf/CMakeLists.txt2
-rw-r--r--source/blender/imbuf/IMB_imbuf.h22
-rw-r--r--source/blender/imbuf/IMB_metadata.h (renamed from source/blender/imbuf/intern/IMB_metadata.h)42
-rw-r--r--source/blender/imbuf/intern/IMB_anim.h3
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c2
-rw-r--r--source/blender/imbuf/intern/anim_movie.c30
-rw-r--r--source/blender/imbuf/intern/colormanagement.c15
-rw-r--r--source/blender/imbuf/intern/indexer.c2
-rw-r--r--source/blender/imbuf/intern/jpeg.c6
-rw-r--r--source/blender/imbuf/intern/metadata.c90
-rw-r--r--source/blender/imbuf/intern/moviecache.c2
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp32
-rw-r--r--source/blender/imbuf/intern/png.c3
-rw-r--r--source/blender/imbuf/intern/scaling.c40
-rw-r--r--source/blender/imbuf/intern/thumbs.c35
-rw-r--r--source/blender/imbuf/intern/thumbs_blend.c1
-rw-r--r--source/blender/imbuf/intern/util.c3
-rw-r--r--source/blender/imbuf/intern/writeimage.c19
-rw-r--r--source/blender/makesdna/DNA_ID.h1
-rw-r--r--source/blender/makesdna/DNA_action_types.h7
-rw-r--r--source/blender/makesdna/DNA_brush_types.h2
-rw-r--r--source/blender/makesdna/DNA_layer_types.h1
-rw-r--r--source/blender/makesdna/DNA_meta_types.h2
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h14
-rw-r--r--source/blender/makesdna/DNA_node_types.h13
-rw-r--r--source/blender/makesdna/DNA_object_enums.h52
-rw-r--r--source/blender/makesdna/DNA_object_fluidsim_types.h (renamed from source/blender/makesdna/DNA_object_fluidsim.h)9
-rw-r--r--source/blender/makesdna/DNA_object_force_types.h (renamed from source/blender/makesdna/DNA_object_force.h)8
-rw-r--r--source/blender/makesdna/DNA_object_types.h39
-rw-r--r--source/blender/makesdna/DNA_particle_types.h25
-rw-r--r--source/blender/makesdna/DNA_scene_types.h45
-rw-r--r--source/blender/makesdna/DNA_screen_types.h7
-rw-r--r--source/blender/makesdna/DNA_smoke_types.h5
-rw-r--r--source/blender/makesdna/DNA_text_types.h4
-rw-r--r--source/blender/makesdna/DNA_texture_types.h2
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h5
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h17
-rw-r--r--source/blender/makesdna/DNA_workspace_types.h10
-rw-r--r--source/blender/makesdna/DNA_world_types.h6
-rw-r--r--source/blender/makesdna/intern/CMakeLists.txt1
-rw-r--r--source/blender/makesdna/intern/dna_genfile.c2
-rw-r--r--source/blender/makesdna/intern/makesdna.c8
-rw-r--r--source/blender/makesrna/RNA_access.h21
-rw-r--r--source/blender/makesrna/RNA_types.h43
-rw-r--r--source/blender/makesrna/intern/rna_ID.c58
-rw-r--r--source/blender/makesrna/intern/rna_access.c123
-rw-r--r--source/blender/makesrna/intern/rna_animation.c4
-rw-r--r--source/blender/makesrna/intern/rna_brush.c1
-rw-r--r--source/blender/makesrna/intern/rna_depsgraph.c31
-rw-r--r--source/blender/makesrna/intern/rna_dynamicpaint.c4
-rw-r--r--source/blender/makesrna/intern/rna_fluidsim.c2
-rw-r--r--source/blender/makesrna/intern/rna_internal.h5
-rw-r--r--source/blender/makesrna/intern/rna_layer.c93
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c38
-rw-r--r--source/blender/makesrna/intern/rna_material.c22
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c13
-rw-r--r--source/blender/makesrna/intern/rna_movieclip.c28
-rw-r--r--source/blender/makesrna/intern/rna_nla.c6
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c144
-rw-r--r--source/blender/makesrna/intern/rna_object.c31
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c124
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c202
-rw-r--r--source/blender/makesrna/intern/rna_particle.c207
-rw-r--r--source/blender/makesrna/intern/rna_render.c30
-rw-r--r--source/blender/makesrna/intern/rna_rigidbody.c25
-rw-r--r--source/blender/makesrna/intern/rna_rna.c18
-rw-r--r--source/blender/makesrna/intern/rna_scene.c98
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c153
-rw-r--r--source/blender/makesrna/intern/rna_screen.c5
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c14
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c58
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c55
-rw-r--r--source/blender/makesrna/intern/rna_space.c62
-rw-r--r--source/blender/makesrna/intern/rna_text_api.c4
-rw-r--r--source/blender/makesrna/intern/rna_ui.c22
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c37
-rw-r--r--source/blender/makesrna/intern/rna_wm.c38
-rw-r--r--source/blender/makesrna/intern/rna_wm_manipulator.c11
-rw-r--r--source/blender/makesrna/intern/rna_workspace.c109
-rw-r--r--source/blender/makesrna/intern/rna_world.c6
-rw-r--r--source/blender/modifiers/CMakeLists.txt11
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c10
-rw-r--r--source/blender/modifiers/intern/MOD_array.c48
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c118
-rw-r--r--source/blender/modifiers/intern/MOD_boolean_util.c790
-rw-r--r--source/blender/modifiers/intern/MOD_build.c14
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c10
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c10
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c12
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c8
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c20
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c12
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim.c16
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim_util.c6
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c12
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c12
-rw-r--r--source/blender/modifiers/intern/MOD_mask.c8
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c12
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.c16
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c10
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.c8
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c9
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c8
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c14
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c8
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c6
-rw-r--r--source/blender/modifiers/intern/MOD_smoke.c14
-rw-r--r--source/blender/modifiers/intern/MOD_softbody.c14
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c34
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c8
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c16
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c12
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c20
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c14
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c24
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c28
-rw-r--r--source/blender/nodes/CMakeLists.txt3
-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/intern/node_util.c5
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c4
-rw-r--r--source/blender/nodes/shader/node_shader_util.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_attribute.c5
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_blackbody.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_displacement.c25
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_hair_info.c1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal_map.c32
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_particle_info.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vectTransform.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_displacement.c83
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_principled.c165
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_scatter.c2
-rw-r--r--source/blender/nodes/texture/node_texture_tree.c10
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_image.c4
-rw-r--r--source/blender/physics/intern/BPH_mass_spring.cpp2
-rw-r--r--source/blender/physics/intern/implicit_blender.c3
-rw-r--r--source/blender/physics/intern/implicit_eigen.cpp2
-rw-r--r--source/blender/python/BPY_extern_clog.h35
-rw-r--r--source/blender/python/bmesh/bmesh_py_ops_call.c8
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c6
-rw-r--r--source/blender/python/gawain/gwn_py_types.c8
-rw-r--r--source/blender/python/generic/bgl.c18
-rw-r--r--source/blender/python/generic/py_capi_utils.c58
-rw-r--r--source/blender/python/generic/py_capi_utils.h4
-rw-r--r--source/blender/python/intern/CMakeLists.txt12
-rw-r--r--source/blender/python/intern/bpy.c3
-rw-r--r--source/blender/python/intern/bpy_app.c5
-rw-r--r--source/blender/python/intern/bpy_app_build_options.c7
-rw-r--r--source/blender/python/intern/bpy_interface.c18
-rw-r--r--source/blender/python/intern/bpy_msgbus.c4
-rw-r--r--source/blender/python/intern/bpy_operator.c2
-rw-r--r--source/blender/python/intern/bpy_rna.c76
-rw-r--r--source/blender/python/intern/bpy_rna.h4
-rw-r--r--source/blender/python/intern/bpy_rna_array.c7
-rw-r--r--source/blender/python/intern/gpu_offscreen.c7
-rw-r--r--source/blender/python/mathutils/mathutils_Euler.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c8
-rw-r--r--source/blender/python/mathutils/mathutils_bvhtree.c2
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c22
-rw-r--r--source/blender/render/extern/include/RE_engine.h19
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h20
-rw-r--r--source/blender/render/extern/include/RE_render_ext.h21
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h2
-rw-r--r--source/blender/render/intern/include/pointdensity.h5
-rw-r--r--source/blender/render/intern/include/render_result.h23
-rw-r--r--source/blender/render/intern/include/render_types.h3
-rw-r--r--source/blender/render/intern/include/renderdatabase.h3
-rw-r--r--source/blender/render/intern/source/bake.c16
-rw-r--r--source/blender/render/intern/source/convertblender.c242
-rw-r--r--source/blender/render/intern/source/envmap.c8
-rw-r--r--source/blender/render/intern/source/external_engine.c132
-rw-r--r--source/blender/render/intern/source/imagetexture.c8
-rw-r--r--source/blender/render/intern/source/initrender.c7
-rw-r--r--source/blender/render/intern/source/multires_bake.c6
-rw-r--r--source/blender/render/intern/source/occlusion.c16
-rw-r--r--source/blender/render/intern/source/pipeline.c194
-rw-r--r--source/blender/render/intern/source/pointdensity.c88
-rw-r--r--source/blender/render/intern/source/render_result.c29
-rw-r--r--source/blender/render/intern/source/render_texture.c8
-rw-r--r--source/blender/render/intern/source/renderdatabase.c3
-rw-r--r--source/blender/render/intern/source/shadbuf.c24
-rw-r--r--source/blender/render/intern/source/sss.c4
-rw-r--r--source/blender/render/intern/source/voxeldata.c2
-rw-r--r--source/blender/render/intern/source/zbuf.c555
-rw-r--r--source/blender/windowmanager/CMakeLists.txt3
-rw-r--r--source/blender/windowmanager/WM_api.h24
-rw-r--r--source/blender/windowmanager/WM_keymap.h3
-rw-r--r--source/blender/windowmanager/WM_types.h19
-rw-r--r--source/blender/windowmanager/intern/wm.c24
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c157
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c112
-rw-r--r--source/blender/windowmanager/intern/wm_files.c56
-rw-r--r--source/blender/windowmanager/intern/wm_files_link.c19
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c40
-rw-r--r--source/blender/windowmanager/intern/wm_gesture_ops.c52
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c89
-rw-r--r--source/blender/windowmanager/intern/wm_jobs.c8
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c47
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c107
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c2
-rw-r--r--source/blender/windowmanager/intern/wm_stereo.c87
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c324
-rw-r--r--source/blender/windowmanager/intern/wm_window.c334
-rw-r--r--source/blender/windowmanager/manipulators/WM_manipulator_api.h2
-rw-r--r--source/blender/windowmanager/manipulators/WM_manipulator_types.h1
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c12
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h1
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c25
-rw-r--r--source/blender/windowmanager/message_bus/intern/wm_message_bus.c5
-rw-r--r--source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c5
-rw-r--r--source/blender/windowmanager/message_bus/intern/wm_message_bus_static.c2
-rw-r--r--source/blender/windowmanager/message_bus/wm_message_bus.h2
-rw-r--r--source/blender/windowmanager/wm.h3
-rw-r--r--source/blender/windowmanager/wm_draw.h4
-rw-r--r--source/blender/windowmanager/wm_subwindow.h52
-rw-r--r--source/blender/windowmanager/wm_window.h2
-rw-r--r--source/blenderplayer/CMakeLists.txt8
-rw-r--r--source/blenderplayer/bad_level_call_stubs/CMakeLists.txt1
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c67
-rw-r--r--source/creator/CMakeLists.txt71
-rw-r--r--source/creator/creator.c12
-rw-r--r--source/creator/creator_args.c187
-rw-r--r--source/creator/creator_signals.c40
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp16
-rw-r--r--source/gameengine/Ketsji/KX_FontObject.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp4
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp2
-rw-r--r--source/gameengine/VideoTexture/VideoFFmpeg.cpp8
m---------source/tools0
972 files changed, 36824 insertions, 26546 deletions
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index a185d10a6bb..8a93e9c94d6 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -67,8 +67,9 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_modifier_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_nla_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_node_types.h
- ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_object_fluidsim.h
- ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_object_force.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_object_fluidsim_types.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_object_force_types.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_object_enums.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_object_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_outliner_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_packedFile_types.h
diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc
index 945f82e8827..ed5b59d08e2 100644
--- a/source/blender/alembic/intern/abc_exporter.cc
+++ b/source/blender/alembic/intern/abc_exporter.cc
@@ -168,7 +168,7 @@ static bool export_object(const ExportSettings * const settings, const Base * co
/* ************************************************************************** */
-AbcExporter::AbcExporter(Main *bmain, EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+AbcExporter::AbcExporter(Main *bmain, EvaluationContext *eval_ctx, Scene *scene,
Depsgraph *depsgraph,
const char *filename, ExportSettings &settings)
: m_bmain(bmain)
@@ -178,7 +178,6 @@ AbcExporter::AbcExporter(Main *bmain, EvaluationContext *eval_ctx, Scene *scene,
, m_shape_sampling_index(0)
, m_eval_ctx(eval_ctx)
, m_scene(scene)
- , m_view_layer(view_layer)
, m_depsgraph(depsgraph)
, m_writer(NULL)
{}
@@ -657,5 +656,5 @@ void AbcExporter::setCurrentFrame(Main *bmain, double t)
{
m_scene->r.cfra = static_cast<int>(t);
m_scene->r.subframe = static_cast<float>(t) - m_scene->r.cfra;
- BKE_scene_graph_update_for_newframe(bmain->eval_ctx, m_depsgraph, bmain, m_scene, m_view_layer);
+ BKE_scene_graph_update_for_newframe(m_depsgraph, bmain);
}
diff --git a/source/blender/alembic/intern/abc_exporter.h b/source/blender/alembic/intern/abc_exporter.h
index 2a34ad2b25d..9c9c21af12f 100644
--- a/source/blender/alembic/intern/abc_exporter.h
+++ b/source/blender/alembic/intern/abc_exporter.h
@@ -95,7 +95,6 @@ class AbcExporter {
EvaluationContext *m_eval_ctx;
Scene *m_scene;
- ViewLayer *m_view_layer;
Depsgraph *m_depsgraph;
ArchiveWriter *m_writer;
@@ -107,7 +106,7 @@ class AbcExporter {
std::vector<AbcObjectWriter *> m_shapes;
public:
- AbcExporter(Main *bmain, EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ AbcExporter(Main *bmain, EvaluationContext *eval_ctx, Scene *scene,
Depsgraph *depsgraph,
const char *filename, ExportSettings &settings);
~AbcExporter();
diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc
index fa2bbb8dfc3..c2c99e2b11f 100644
--- a/source/blender/alembic/intern/abc_mesh.cc
+++ b/source/blender/alembic/intern/abc_mesh.cc
@@ -31,7 +31,7 @@ extern "C" {
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
-#include "DNA_object_fluidsim.h"
+#include "DNA_object_fluidsim_types.h"
#include "DNA_object_types.h"
#include "BLI_math_geom.h"
diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc
index 5e93779b5f6..cb01efb2cf4 100644
--- a/source/blender/alembic/intern/alembic_capi.cc
+++ b/source/blender/alembic/intern/alembic_capi.cc
@@ -265,8 +265,7 @@ static void export_startjob(void *customdata, short *stop, short *do_update, flo
try {
Scene *scene = data->scene;
- ViewLayer *view_layer = data->view_layer;
- AbcExporter exporter(data->bmain, &data->eval_ctx, scene, view_layer, data->depsgraph, data->filename, data->settings);
+ AbcExporter exporter(data->bmain, &data->eval_ctx, scene, data->depsgraph, data->filename, data->settings);
const int orig_frame = CFRA;
@@ -276,7 +275,7 @@ static void export_startjob(void *customdata, short *stop, short *do_update, flo
if (CFRA != orig_frame) {
CFRA = orig_frame;
- BKE_scene_graph_update_for_newframe(data->bmain->eval_ctx, data->depsgraph, data->bmain, scene, data->view_layer);
+ BKE_scene_graph_update_for_newframe(data->depsgraph, data->bmain);
}
data->export_ok = !data->was_canceled;
@@ -843,7 +842,7 @@ static void import_endjob(void *user_data)
lc = BKE_layer_collection_get_active(view_layer);
if (lc == NULL) {
- BLI_assert(BLI_listbase_count_ex(&view_layer->layer_collections, 1) == 0);
+ BLI_assert(BLI_listbase_count_at_most(&view_layer->layer_collections, 1) == 0);
/* when there is no collection linked to this ViewLayer, create one */
SceneCollection *sc = BKE_collection_add(&data->scene->id, NULL, COLLECTION_TYPE_NONE, NULL);
lc = BKE_collection_link(view_layer, sc);
@@ -858,9 +857,11 @@ static void import_endjob(void *user_data)
base = BKE_view_layer_base_find(view_layer, ob);
BKE_view_layer_base_select(view_layer, base);
- DEG_id_tag_update_ex(data->bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update_ex(data->bmain, &ob->id,
+ OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME | DEG_TAG_BASE_FLAGS_UPDATE);
}
+ DEG_id_tag_update(&data->scene->id, DEG_TAG_BASE_FLAGS_UPDATE);
DEG_relations_tag_update(data->bmain);
}
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index 22559edad22..668588435b4 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -33,6 +33,7 @@
#define __BLF_API_H__
#include "BLI_compiler_attrs.h"
+#include "BLI_sys_types.h"
/* enable this only if needed (unused circa 2016) */
#define BLF_BLUR_ENABLE 0
@@ -46,6 +47,10 @@ void BLF_exit(void);
void BLF_default_dpi(int dpi);
void BLF_default_set(int fontid);
int BLF_default(void); /* get default font ID so we can pass it to other functions */
+void BLF_batch_reset(void); /* call when changing opengl context. */
+
+void BLF_antialias_set(bool enabled);
+bool BLF_antialias_get(void);
void BLF_cache_clear(void);
@@ -90,6 +95,12 @@ void BLF_color3fv_alpha(int fontid, const float rgb[3], float alpha);
*/
void BLF_matrix(int fontid, const float m[16]);
+/* Batch drawcalls together as long as
+ * the modelview matrix and the font remain unchanged. */
+void BLF_batch_draw_begin(void);
+void BLF_batch_draw_flush(void);
+void BLF_batch_draw_end(void);
+
/* Draw the string using the default font, size and dpi. */
void BLF_draw_default(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL();
void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL();
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 24347d57917..fafee125264 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -85,6 +85,7 @@ static FontBLF *global_font[BLF_MAX_FONT] = {NULL};
static int global_font_default = -1;
static int global_font_points = 11;
static int global_font_dpi = 72;
+static bool global_use_antialias = true;
/* XXX, should these be made into global_font_'s too? */
int blf_mono_font = -1;
@@ -131,6 +132,11 @@ void BLF_exit(void)
blf_font_exit();
}
+void BLF_batch_reset(void)
+{
+ blf_batch_draw_vao_clear();
+}
+
void BLF_cache_clear(void)
{
FontBLF *font;
@@ -138,8 +144,10 @@ void BLF_cache_clear(void)
for (i = 0; i < BLF_MAX_FONT; i++) {
font = global_font[i];
- if (font)
+ if (font) {
blf_glyph_cache_clear(font);
+ blf_kerning_cache_clear(font);
+ }
}
}
@@ -182,6 +190,16 @@ int BLF_default(void)
return global_font_default;
}
+void BLF_antialias_set(bool enabled)
+{
+ global_use_antialias = enabled;
+}
+
+bool BLF_antialias_get(void)
+{
+ return global_use_antialias;
+}
+
int BLF_load(const char *name)
{
FontBLF *font;
@@ -524,6 +542,26 @@ void BLF_color3f(int fontid, float r, float g, float b)
BLF_color4fv(fontid, rgba);
}
+void BLF_batch_draw_begin(void)
+{
+ BLI_assert(g_batch.enabled == false);
+ g_batch.enabled = true;
+}
+
+void BLF_batch_draw_flush(void)
+{
+ if (g_batch.enabled) {
+ blf_batch_draw();
+ }
+}
+
+void BLF_batch_draw_end(void)
+{
+ BLI_assert(g_batch.enabled == true);
+ blf_batch_draw(); /* Draw remaining glyphs */
+ g_batch.enabled = false;
+}
+
void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
{
ASSERT_DEFAULT_SET;
@@ -550,8 +588,11 @@ static void blf_draw_gl__start(FontBLF *font)
* in BLF_position (old ui_rasterpos_safe).
*/
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ /* always bind the texture for the first glyph */
+ font->tex_bind_state = 0;
+
+ if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) == 0)
+ return; /* glyphs will be translated individually and batched. */
gpuPushMatrix();
@@ -565,35 +606,12 @@ static void blf_draw_gl__start(FontBLF *font)
if (font->flags & BLF_ROTATION)
gpuRotate2D(RAD2DEG(font->angle));
-
-#ifndef BLF_STANDALONE
- Gwn_VertFormat *format = immVertexFormat();
- unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned int texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
-
- BLI_assert(pos == BLF_POS_ID);
- BLI_assert(texCoord == BLF_COORD_ID);
- BLI_assert(color == BLF_COLOR_ID);
-
- UNUSED_VARS_NDEBUG(pos, texCoord, color);
-
- immBindBuiltinProgram(GPU_SHADER_TEXT);
-#endif
-
- /* always bind the texture for the first glyph */
- font->tex_bind_state = -1;
}
-static void blf_draw_gl__end(void)
+static void blf_draw_gl__end(FontBLF *font)
{
- gpuPopMatrix();
-
-#ifndef BLF_STANDALONE
- immUnbindProgram();
-#endif
-
- glDisable(GL_BLEND);
+ if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) != 0)
+ gpuPopMatrix();
}
void BLF_draw_ex(
@@ -612,7 +630,7 @@ void BLF_draw_ex(
else {
blf_font_draw(font, str, len, r_info);
}
- blf_draw_gl__end();
+ blf_draw_gl__end(font);
}
}
void BLF_draw(int fontid, const char *str, size_t len)
@@ -641,7 +659,7 @@ void BLF_draw_ascii_ex(
else {
blf_font_draw_ascii(font, str, len, r_info);
}
- blf_draw_gl__end();
+ blf_draw_gl__end(font);
}
}
void BLF_draw_ascii(int fontid, const char *str, size_t len)
@@ -665,7 +683,7 @@ int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
if (font && font->glyph_cache) {
blf_draw_gl__start(font);
columns = blf_font_draw_mono(font, str, len, cwidth);
- blf_draw_gl__end();
+ blf_draw_gl__end(font);
}
return columns;
@@ -799,7 +817,7 @@ int BLF_height_max(int fontid)
FontBLF *font = blf_get(fontid);
if (font && font->glyph_cache) {
- return font->glyph_cache->max_glyph_height;
+ return font->glyph_cache->glyph_height_max;
}
return 0;
@@ -810,7 +828,7 @@ float BLF_width_max(int fontid)
FontBLF *font = blf_get(fontid);
if (font && font->glyph_cache) {
- return font->glyph_cache->max_glyph_width;
+ return font->glyph_cache->glyph_width_max;
}
return 0.0f;
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 5846f7a29e4..c12303dcfc0 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -58,7 +58,11 @@
#include "BIF_gl.h"
#include "BLF_api.h"
+#include "UI_interface.h"
+
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "GPU_batch.h"
#include "blf_internal_types.h"
#include "blf_internal.h"
@@ -69,12 +73,157 @@
# define FT_New_Face FT_New_Face__win32_compat
#endif
+/* Batching buffer for drawing. */
+BatchBLF g_batch;
+
/* freetype2 handle ONLY for this file!. */
static FT_Library ft_lib;
static SpinLock ft_lib_mutex;
+/* -------------------------------------------------------------------- */
+/** \name Glyph Batching
+ * \{ */
+/**
+ * Drawcalls are precious! make them count!
+ * Since most of the Text elems are not covered by other UI elements, we can
+ * group some strings together and render them in one drawcall. This behaviour
+ * is on demand only, between BLF_batch_start() and BLF_batch_end().
+ **/
+static void blf_batch_draw_init(void)
+{
+ Gwn_VertFormat format = {0};
+ g_batch.pos_loc = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ g_batch.tex_loc = GWN_vertformat_attr_add(&format, "tex", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ g_batch.col_loc = GWN_vertformat_attr_add(&format, "col", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ g_batch.verts = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STREAM);
+ GWN_vertbuf_data_alloc(g_batch.verts, BLF_BATCH_DRAW_LEN_MAX);
+
+ GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.tex_loc, &g_batch.tex_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
+ g_batch.glyph_len = 0;
+
+ g_batch.batch = GWN_batch_create_ex(GWN_PRIM_POINTS, g_batch.verts, NULL, GWN_BATCH_OWNS_VBO);
+}
+
+static void blf_batch_draw_exit(void)
+{
+ GWN_BATCH_DISCARD_SAFE(g_batch.batch);
+}
+
+void blf_batch_draw_vao_clear(void)
+{
+ if (g_batch.batch) {
+ gwn_batch_vao_cache_clear(g_batch.batch);
+ }
+}
+
+void blf_batch_draw_begin(FontBLF *font)
+{
+ if (g_batch.batch == NULL) {
+ blf_batch_draw_init();
+ }
+
+ const bool font_changed = (g_batch.font != font);
+ const bool simple_shader = ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) == 0);
+ const bool shader_changed = (simple_shader != g_batch.simple_shader);
+
+ g_batch.active = g_batch.enabled && simple_shader;
+
+ if (simple_shader) {
+ /* Offset is applied to each glyph. */
+ copy_v2_v2(g_batch.ofs, font->pos);
+ }
+ else {
+ /* Offset is baked in modelview mat. */
+ zero_v2(g_batch.ofs);
+ }
+
+ if (g_batch.active) {
+ float gpumat[4][4];
+ gpuGetModelViewMatrix(gpumat);
+
+ bool mat_changed = (memcmp(gpumat, g_batch.mat, sizeof(g_batch.mat)) != 0);
+
+ if (mat_changed) {
+ /* Modelviewmat is no longer the same.
+ * Flush cache but with the previous mat. */
+ gpuPushMatrix();
+ gpuLoadMatrix(g_batch.mat);
+ }
+
+ /* flush cache if config is not the same. */
+ if (mat_changed || font_changed || shader_changed) {
+ blf_batch_draw();
+ g_batch.simple_shader = simple_shader;
+ g_batch.font = font;
+ }
+ else {
+ /* Nothing changed continue batching. */
+ return;
+ }
+
+ if (mat_changed) {
+ gpuPopMatrix();
+ /* Save for next memcmp. */
+ memcpy(g_batch.mat, gpumat, sizeof(g_batch.mat));
+ }
+ }
+ else {
+ /* flush cache */
+ blf_batch_draw();
+ g_batch.font = font;
+ g_batch.simple_shader = simple_shader;
+ }
+}
+
+void blf_batch_draw(void)
+{
+ if (g_batch.glyph_len == 0)
+ return;
+
+ glEnable(GL_BLEND);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ /* We need to flush widget base first to ensure correct ordering. */
+ UI_widgetbase_draw_cache_flush();
+
+ BLI_assert(g_batch.tex_bind_state != 0); /* must still be valid */
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, g_batch.tex_bind_state);
+
+ GWN_vertbuf_vertex_count_set(g_batch.verts, g_batch.glyph_len);
+ GWN_vertbuf_use(g_batch.verts); /* send data */
+
+ GPUBuiltinShader shader = (g_batch.simple_shader) ? GPU_SHADER_TEXT_SIMPLE : GPU_SHADER_TEXT;
+ GWN_batch_program_set_builtin(g_batch.batch, shader);
+ GWN_batch_uniform_1i(g_batch.batch, "glyph", 0);
+ GWN_batch_draw(g_batch.batch);
+
+ glDisable(GL_BLEND);
+
+ /* restart to 1st vertex data pointers */
+ GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.tex_loc, &g_batch.tex_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
+ g_batch.glyph_len = 0;
+}
+
+static void blf_batch_draw_end(void)
+{
+ if (!g_batch.active) {
+ blf_batch_draw();
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
int blf_font_init(void)
{
+ memset(&g_batch, 0, sizeof(g_batch));
BLI_spin_init(&ft_lib_mutex);
return FT_Init_FreeType(&ft_lib);
}
@@ -83,6 +232,7 @@ void blf_font_exit(void)
{
FT_Done_FreeType(ft_lib);
BLI_spin_end(&ft_lib_mutex);
+ blf_batch_draw_exit();
}
void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
@@ -90,6 +240,14 @@ void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
GlyphCacheBLF *gc;
FT_Error err;
+ gc = blf_glyph_cache_find(font, size, dpi);
+ if (gc) {
+ font->glyph_cache = gc;
+ /* Optimization: do not call FT_Set_Char_Size if size did not change. */
+ if (font->size == size && font->dpi == dpi)
+ return;
+ }
+
err = FT_Set_Char_Size(font->face, 0, (FT_F26Dot6)(size * 64), dpi, dpi);
if (err) {
/* FIXME: here we can go through the fixed size and choice a close one */
@@ -100,10 +258,7 @@ void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
font->size = size;
font->dpi = dpi;
- gc = blf_glyph_cache_find(font, size, dpi);
- if (gc)
- font->glyph_cache = gc;
- else {
+ if (!gc) {
gc = blf_glyph_cache_new(font);
if (gc)
font->glyph_cache = gc;
@@ -131,6 +286,20 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
}
}
+static void blf_font_ensure_ascii_kerning(FontBLF *font, const FT_UInt kern_mode)
+{
+ KerningCacheBLF *kc = font->kerning_cache;
+
+ font->kerning_mode = kern_mode;
+
+ if (!kc || kc->mode != kern_mode) {
+ font->kerning_cache = kc = blf_kerning_cache_find(font);
+ if (!kc) {
+ font->kerning_cache = kc = blf_kerning_cache_new(font);
+ }
+ }
+}
+
/* Fast path for runs of ASCII characters. Given that common UTF-8
* input will consist of an overwhelming majority of ASCII
* characters.
@@ -158,6 +327,26 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
(((_font)->flags & BLF_KERNING_DEFAULT) ? \
ft_kerning_default : (FT_UInt)FT_KERNING_UNFITTED) \
+/* Note,
+ * blf_font_ensure_ascii_kerning(font, kern_mode); must be called before this macro */
+
+#define BLF_KERNING_STEP_FAST(_font, _kern_mode, _g_prev, _g, _c_prev, _c, _pen_x) \
+{ \
+ if (_g_prev) { \
+ FT_Vector _delta; \
+ if (_c_prev < 0x80 && _c < 0x80) { \
+ _pen_x += (_font)->kerning_cache->table[_c][_c_prev]; \
+ } \
+ else if (FT_Get_Kerning((_font)->face, \
+ (_g_prev)->idx, \
+ (_g)->idx, \
+ _kern_mode, \
+ &(_delta)) == 0) \
+ { \
+ _pen_x += (int)_delta.x >> 6; \
+ } \
+ } \
+} (void)0
#define BLF_KERNING_STEP(_font, _kern_mode, _g_prev, _g, _delta, _pen_x) \
{ \
@@ -174,30 +363,12 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
} \
} (void)0
-static unsigned int verts_needed(const FontBLF *font, const char *str, size_t len)
-{
- unsigned int length = (unsigned int)((len == INT_MAX) ? strlen(str) : len);
- unsigned int quad_ct = 1;
-
- if (font->flags & BLF_SHADOW) {
- if (font->shadow == 0)
- quad_ct += 1;
- if (font->shadow <= 4)
- quad_ct += 9; /* 3x3 kernel */
- else
- quad_ct += 25; /* 5x5 kernel */
- }
-
- return length * quad_ct * 6;
-}
-
static void blf_font_draw_ex(
FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
int pen_y)
{
- unsigned int c;
+ unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev = NULL;
- FT_Vector delta;
int pen_x = 0;
size_t i = 0;
GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
@@ -210,9 +381,9 @@ static void blf_font_draw_ex(
BLF_KERNING_VARS(font, has_kerning, kern_mode);
blf_font_ensure_ascii_table(font);
+ blf_font_ensure_ascii_kerning(font, kern_mode);
- immBeginAtMost(GWN_PRIM_TRIS, verts_needed(font, str, len));
- /* at most because some glyphs might be clipped & not drawn */
+ blf_batch_draw_begin(font);
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
@@ -222,16 +393,17 @@ static void blf_font_draw_ex(
if (UNLIKELY(g == NULL))
continue;
if (has_kerning)
- BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
+ BLF_KERNING_STEP_FAST(font, kern_mode, g_prev, g, c_prev, c, pen_x);
/* do not return this loop if clipped, we want every character tested */
blf_glyph_render(font, g, (float)pen_x, (float)pen_y);
pen_x += g->advance_i;
g_prev = g;
+ c_prev = c;
}
- immEnd();
+ blf_batch_draw_end();
if (r_info) {
r_info->lines = 1;
@@ -248,33 +420,34 @@ static void blf_font_draw_ascii_ex(
FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
int pen_y)
{
- unsigned char c;
+ unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev = NULL;
- FT_Vector delta;
int pen_x = 0;
GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
BLF_KERNING_VARS(font, has_kerning, kern_mode);
blf_font_ensure_ascii_table(font);
+ blf_font_ensure_ascii_kerning(font, kern_mode);
- immBeginAtMost(GWN_PRIM_TRIS, verts_needed(font, str, len));
+ blf_batch_draw_begin(font);
while ((c = *(str++)) && len--) {
BLI_assert(c < 128);
if ((g = glyph_ascii_table[c]) == NULL)
continue;
if (has_kerning)
- BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
+ BLF_KERNING_STEP_FAST(font, kern_mode, g_prev, g, c_prev, c, pen_x);
/* do not return this loop if clipped, we want every character tested */
blf_glyph_render(font, g, (float)pen_x, (float)pen_y);
pen_x += g->advance_i;
g_prev = g;
+ c_prev = c;
}
- immEnd();
+ blf_batch_draw_end();
if (r_info) {
r_info->lines = 1;
@@ -298,7 +471,7 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
blf_font_ensure_ascii_table(font);
- immBeginAtMost(GWN_PRIM_TRIS, verts_needed(font, str, len));
+ blf_batch_draw_begin(font);
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
@@ -319,7 +492,7 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
pen_x += cwidth * col;
}
- immEnd();
+ blf_batch_draw_end();
return columns;
}
@@ -329,9 +502,8 @@ static void blf_font_draw_buffer_ex(
FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
int pen_y)
{
- unsigned int c;
+ unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev = NULL;
- FT_Vector delta;
int pen_x = (int)font->pos[0];
int pen_y_basis = (int)font->pos[1] + pen_y;
size_t i = 0;
@@ -347,6 +519,7 @@ static void blf_font_draw_buffer_ex(
BLF_KERNING_VARS(font, has_kerning, kern_mode);
blf_font_ensure_ascii_table(font);
+ blf_font_ensure_ascii_kerning(font, kern_mode);
/* another buffer specific call for color conversion */
@@ -358,7 +531,7 @@ static void blf_font_draw_buffer_ex(
if (UNLIKELY(g == NULL))
continue;
if (has_kerning)
- BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
+ BLF_KERNING_STEP_FAST(font, kern_mode, g_prev, g, c_prev, c, pen_x);
chx = pen_x + ((int)g->pos_x);
chy = pen_y_basis + g->height;
@@ -460,6 +633,7 @@ static void blf_font_draw_buffer_ex(
pen_x += g->advance_i;
g_prev = g;
+ c_prev = c;
}
if (r_info) {
@@ -607,9 +781,8 @@ static void blf_font_boundbox_ex(
FontBLF *font, const char *str, size_t len, rctf *box, struct ResultBLF *r_info,
int pen_y)
{
- unsigned int c;
+ unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev = NULL;
- FT_Vector delta;
int pen_x = 0;
size_t i = 0;
GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
@@ -624,6 +797,7 @@ static void blf_font_boundbox_ex(
box->ymax = -32000.0f;
blf_font_ensure_ascii_table(font);
+ blf_font_ensure_ascii_kerning(font, kern_mode);
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
@@ -633,7 +807,7 @@ static void blf_font_boundbox_ex(
if (UNLIKELY(g == NULL))
continue;
if (has_kerning)
- BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
+ BLF_KERNING_STEP_FAST(font, kern_mode, g_prev, g, c_prev, c, pen_x);
gbox.xmin = (float)pen_x;
gbox.xmax = (float)pen_x + g->advance;
@@ -648,6 +822,7 @@ static void blf_font_boundbox_ex(
pen_x += g->advance_i;
g_prev = g;
+ c_prev = c;
}
if (box->xmin > box->xmax) {
@@ -756,7 +931,7 @@ static void blf_font_wrap_apply(
wrap.start = wrap.last[0];
i = wrap.last[1];
pen_x = 0;
- pen_y -= font->glyph_cache->max_glyph_height;
+ pen_y -= font->glyph_cache->glyph_height_max;
g_prev = NULL;
lines += 1;
continue;
@@ -928,6 +1103,8 @@ void blf_font_free(FontBLF *font)
blf_glyph_cache_free(gc);
}
+ blf_kerning_cache_clear(font);
+
FT_Done_Face(font->face);
if (font->filename)
MEM_freeN(font->filename);
@@ -962,11 +1139,13 @@ static void blf_font_fill(FontBLF *font)
font->dpi = 0;
font->size = 0;
BLI_listbase_clear(&font->cache);
+ BLI_listbase_clear(&font->kerning_caches);
font->glyph_cache = NULL;
+ font->kerning_cache = NULL;
#if BLF_BLUR_ENABLE
font->blur = 0;
#endif
- font->max_tex_size = -1;
+ font->tex_size_max = -1;
font->buf_info.fbuf = NULL;
font->buf_info.cbuf = NULL;
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index a7d52e96800..96854db66dd 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -56,13 +56,69 @@
#include "BLF_api.h"
#ifndef BLF_STANDALONE
-#include "GPU_immediate.h"
+# include "GPU_immediate.h"
#endif
#include "blf_internal_types.h"
#include "blf_internal.h"
#include "BLI_strict_flags.h"
+#include "BLI_math_vector.h"
+
+KerningCacheBLF *blf_kerning_cache_find(FontBLF *font)
+{
+ KerningCacheBLF *p;
+
+ p = (KerningCacheBLF *)font->kerning_caches.first;
+ while (p) {
+ if (p->mode == font->kerning_mode)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
+/* Create a new glyph cache for the current kerning mode. */
+KerningCacheBLF *blf_kerning_cache_new(FontBLF *font)
+{
+ KerningCacheBLF *kc;
+
+ kc = (KerningCacheBLF *)MEM_callocN(sizeof(KerningCacheBLF), "blf_kerning_cache_new");
+ kc->next = NULL;
+ kc->prev = NULL;
+ kc->mode = font->kerning_mode;
+
+ unsigned int i, j;
+ for (i = 0; i < 0x80; i++) {
+ for (j = 0; j < 0x80; j++) {
+ GlyphBLF *g = blf_glyph_search(font->glyph_cache, i);
+ if (!g) {
+ FT_UInt glyph_index = FT_Get_Char_Index(font->face, i);
+ g = blf_glyph_add(font, glyph_index, i);
+ }
+ /* Cannot fail since it has been added just before. */
+ GlyphBLF *g_prev = blf_glyph_search(font->glyph_cache, j);
+
+ FT_Vector delta = {.x = 0, .y = 0};
+ if (FT_Get_Kerning(font->face, g_prev->idx, g->idx, kc->mode,
+ &delta) == 0) {
+ kc->table[i][j] = (int)delta.x >> 6;
+ }
+ else {
+ kc->table[i][j] = 0;
+ }
+ }
+ }
+
+ BLI_addhead(&font->kerning_caches, kc);
+ return kc;
+}
+
+void blf_kerning_cache_clear(FontBLF *font)
+{
+ font->kerning_cache = NULL;
+ BLI_freelistN(&font->kerning_caches);
+}
GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, unsigned int size, unsigned int dpi)
{
@@ -92,34 +148,34 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
memset(gc->bucket, 0, sizeof(gc->bucket));
gc->textures = (GLuint *)MEM_mallocN(sizeof(GLuint) * 256, __func__);
- gc->ntex = 256;
- gc->cur_tex = BLF_CURTEX_UNSET;
- gc->x_offs = 0;
- gc->y_offs = 0;
- gc->pad = 3;
-
- gc->num_glyphs = (int)font->face->num_glyphs;
- gc->rem_glyphs = (int)font->face->num_glyphs;
+ gc->textures_len = 256;
+ gc->texture_current = BLF_TEXTURE_UNSET;
+ gc->offset_x = 3; /* enough padding for blur */
+ gc->offset_y = 3; /* enough padding for blur */
+ gc->pad = 6;
+
+ gc->glyphs_len_max = (int)font->face->num_glyphs;
+ gc->glyphs_len_free = (int)font->face->num_glyphs;
gc->ascender = ((float)font->face->size->metrics.ascender) / 64.0f;
gc->descender = ((float)font->face->size->metrics.descender) / 64.0f;
if (FT_IS_SCALABLE(font->face)) {
- gc->max_glyph_width = (int)((float)(font->face->bbox.xMax - font->face->bbox.xMin) *
+ gc->glyph_width_max = (int)((float)(font->face->bbox.xMax - font->face->bbox.xMin) *
(((float)font->face->size->metrics.x_ppem) /
((float)font->face->units_per_EM)));
- gc->max_glyph_height = (int)((float)(font->face->bbox.yMax - font->face->bbox.yMin) *
+ gc->glyph_height_max = (int)((float)(font->face->bbox.yMax - font->face->bbox.yMin) *
(((float)font->face->size->metrics.y_ppem) /
((float)font->face->units_per_EM)));
}
else {
- gc->max_glyph_width = (int)(((float)font->face->size->metrics.max_advance) / 64.0f);
- gc->max_glyph_height = (int)(((float)font->face->size->metrics.height) / 64.0f);
+ gc->glyph_width_max = (int)(((float)font->face->size->metrics.max_advance) / 64.0f);
+ gc->glyph_height_max = (int)(((float)font->face->size->metrics.height) / 64.0f);
}
/* can happen with size 1 fonts */
- CLAMP_MIN(gc->max_glyph_width, 1);
- CLAMP_MIN(gc->max_glyph_height, 1);
+ CLAMP_MIN(gc->glyph_width_max, 1);
+ CLAMP_MIN(gc->glyph_height_max, 1);
gc->p2_width = 0;
gc->p2_height = 0;
@@ -149,9 +205,10 @@ void blf_glyph_cache_free(GlyphCacheBLF *gc)
}
}
- if (gc->cur_tex != BLF_CURTEX_UNSET)
- glDeleteTextures((int)gc->cur_tex + 1, gc->textures);
- MEM_freeN((void *)gc->textures);
+ if (gc->texture_current != BLF_TEXTURE_UNSET) {
+ glDeleteTextures((int)gc->texture_current + 1, gc->textures);
+ }
+ MEM_freeN(gc->textures);
MEM_freeN(gc);
}
@@ -160,30 +217,35 @@ static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc)
int i;
/* move the index. */
- gc->cur_tex++;
+ gc->texture_current++;
- if (UNLIKELY(gc->cur_tex >= gc->ntex)) {
- gc->ntex *= 2;
- gc->textures = (GLuint *)MEM_reallocN((void *)gc->textures, sizeof(GLuint) * gc->ntex);
+ if (UNLIKELY(gc->texture_current >= gc->textures_len)) {
+ gc->textures_len *= 2;
+ gc->textures = MEM_reallocN((void *)gc->textures, sizeof(GLuint) * gc->textures_len);
}
- gc->p2_width = (int)blf_next_p2((unsigned int)((gc->rem_glyphs * gc->max_glyph_width) + (gc->pad * 2)));
- if (gc->p2_width > font->max_tex_size)
- gc->p2_width = font->max_tex_size;
+ gc->p2_width = (int)blf_next_p2((unsigned int)((gc->glyphs_len_free * gc->glyph_width_max) + (gc->pad * 2)));
+ if (gc->p2_width > font->tex_size_max) {
+ gc->p2_width = font->tex_size_max;
+ }
- i = (int)((gc->p2_width - (gc->pad * 2)) / gc->max_glyph_width);
- gc->p2_height = (int)blf_next_p2((unsigned int)(((gc->num_glyphs / i) + 1) * gc->max_glyph_height));
+ i = (int)((gc->p2_width - (gc->pad * 2)) / gc->glyph_width_max);
+ gc->p2_height = (int)blf_next_p2((unsigned int)(((gc->glyphs_len_max / i) + 1) * gc->glyph_height_max + (gc->pad * 2)));
- if (gc->p2_height > font->max_tex_size)
- gc->p2_height = font->max_tex_size;
+ if (gc->p2_height > font->tex_size_max) {
+ gc->p2_height = font->tex_size_max;
+ }
- glGenTextures(1, &gc->textures[gc->cur_tex]);
- glBindTexture(GL_TEXTURE_2D, (font->tex_bind_state = gc->textures[gc->cur_tex]));
+ glGenTextures(1, &gc->textures[gc->texture_current]);
+ glBindTexture(GL_TEXTURE_2D, (font->tex_bind_state = gc->textures[gc->texture_current]));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, gc->p2_width, gc->p2_height, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
+
+ unsigned char *pixels = MEM_callocN((size_t)gc->p2_width * (size_t)gc->p2_height, "BLF texture init");
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, gc->p2_width, gc->p2_height, 0, GL_RED, GL_UNSIGNED_BYTE, pixels);
+ MEM_freeN(pixels);
}
GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c)
@@ -207,7 +269,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
GlyphBLF *g;
FT_Error err;
FT_Bitmap bitmap, tempbitmap;
- const bool is_sharp = (U.text_render & USER_TEXT_DISABLE_AA) != 0;
+ const bool is_sharp = !BLF_antialias_get();
int flags = FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP;
FT_BBox bbox;
unsigned int key;
@@ -267,8 +329,8 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
g = (GlyphBLF *)MEM_callocN(sizeof(GlyphBLF), "blf_glyph_add");
g->c = c;
g->idx = (FT_UInt)index;
- g->xoff = -1;
- g->yoff = -1;
+ g->offset_x = -1;
+ g->offset_y = -1;
bitmap = slot->bitmap;
g->width = (int)bitmap.width;
g->height = (int)bitmap.rows;
@@ -282,8 +344,8 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
}
}
- g->bitmap = (unsigned char *)MEM_mallocN((size_t)(g->width * g->height), "glyph bitmap");
- memcpy((void *)g->bitmap, (void *)bitmap.buffer, (size_t)(g->width * g->height));
+ g->bitmap = (unsigned char *)MEM_mallocN((size_t)g->width * (size_t)g->height, "glyph bitmap");
+ memcpy((void *)g->bitmap, (void *)bitmap.buffer, (size_t)g->width * (size_t)g->height);
}
g->advance = ((float)slot->advance.x) / 64.0f;
@@ -316,83 +378,49 @@ void blf_glyph_free(GlyphBLF *g)
MEM_freeN(g);
}
-static void blf_texture_draw(const unsigned char color[4], float uv[2][2], float dx, float y1, float dx1, float y2)
+static void blf_texture_draw(const unsigned char color[4], const float uv[2][2], float x1, float y1, float x2, float y2)
{
- /* First triangle. */
- immAttrib2f(BLF_COORD_ID, uv[0][0], uv[0][1]);
- immSkipAttrib(BLF_COLOR_ID); /* skip color of most vertices */
- immVertex2f(BLF_POS_ID, dx, y1);
-
- immAttrib2f(BLF_COORD_ID, uv[0][0], uv[1][1]);
- immSkipAttrib(BLF_COLOR_ID);
- immVertex2f(BLF_POS_ID, dx, y2);
-
- immAttrib2f(BLF_COORD_ID, uv[1][0], uv[1][1]);
- immAttrib4ubv(BLF_COLOR_ID, color); /* set color of provoking vertex */
- immVertex2f(BLF_POS_ID, dx1, y2);
-
- /* Second triangle. */
- immAttrib2f(BLF_COORD_ID, uv[0][0], uv[0][1]);
- immSkipAttrib(BLF_COLOR_ID); /* skip color of most vertices */
- immVertex2f(BLF_POS_ID, dx, y1);
-
- immAttrib2f(BLF_COORD_ID, uv[1][0], uv[1][1]);
- immSkipAttrib(BLF_COLOR_ID);
- immVertex2f(BLF_POS_ID, dx1, y2);
-
- immAttrib2f(BLF_COORD_ID, uv[1][0], uv[0][1]);
- immAttrib4ubv(BLF_COLOR_ID, color); /* set color of provoking vertex */
- immVertex2f(BLF_POS_ID, dx1, y1);
+ /* Only one vertex per glyph, geometry shader expand it into a quad. */
+ /* TODO Get rid of Geom Shader because it's not optimal AT ALL for the GPU */
+ copy_v4_fl4(GWN_vertbuf_raw_step(&g_batch.pos_step), x1 + g_batch.ofs[0], y1 + g_batch.ofs[1],
+ x2 + g_batch.ofs[0], y2 + g_batch.ofs[1]);
+ copy_v4_v4(GWN_vertbuf_raw_step(&g_batch.tex_step), (float *)uv);
+ copy_v4_v4_uchar(GWN_vertbuf_raw_step(&g_batch.col_step), color);
+ g_batch.glyph_len++;
+ /* Flush cache if it's full. */
+ if (g_batch.glyph_len == BLF_BATCH_DRAW_LEN_MAX) {
+ blf_batch_draw();
+ }
}
-static void blf_texture5_draw(const unsigned char color_in[4], float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture5_draw(const unsigned char color_in[4], int tex_w, int tex_h, const float uv[2][2],
+ float x1, float y1, float x2, float y2)
{
- const float soft[25] = {1 / 60.0f, 1 / 60.0f, 2 / 60.0f, 1 / 60.0f, 1 / 60.0f,
- 1 / 60.0f, 3 / 60.0f, 5 / 60.0f, 3 / 60.0f, 1 / 60.0f,
- 2 / 60.0f, 5 / 60.0f, 8 / 60.0f, 5 / 60.0f, 2 / 60.0f,
- 1 / 60.0f, 3 / 60.0f, 5 / 60.0f, 3 / 60.0f, 1 / 60.0f,
- 1 / 60.0f, 1 / 60.0f, 2 / 60.0f, 1 / 60.0f, 1 / 60.0f};
-
- const float *fp = soft;
- unsigned char color[4];
- float dx, dy;
-
- color[0] = color_in[0];
- color[1] = color_in[1];
- color[2] = color_in[2];
-
- const float alpha_in = (1 / 255.0f) * color_in[3];
-
- for (dx = -2; dx < 3; dx++) {
- for (dy = -2; dy < 3; dy++, fp++) {
- color[3] = FTOCHAR(*fp * alpha_in);
- blf_texture_draw(color, uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
- }
- }
+ float ofs[2] = { 2 / (float)tex_w, 2 / (float)tex_h };
+ float uv_flag[2][2];
+ copy_v4_v4((float *)uv_flag, (float *)uv);
+ /* flag the x and y component signs for 5x5 bluring */
+ uv_flag[0][0] = -(uv_flag[0][0] - ofs[0]);
+ uv_flag[0][1] = -(uv_flag[0][1] - ofs[1]);
+ uv_flag[1][0] = -(uv_flag[1][0] + ofs[0]);
+ uv_flag[1][1] = -(uv_flag[1][1] + ofs[1]);
+
+ blf_texture_draw(color_in, uv_flag, x1 - 2, y1 + 2, x2 + 2, y2 - 2);
}
-static void blf_texture3_draw(const unsigned char color_in[4], float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture3_draw(const unsigned char color_in[4], int tex_w, int tex_h, const float uv[2][2],
+ float x1, float y1, float x2, float y2)
{
- const float soft[9] = {1 / 16.0f, 2 / 16.0f, 1 / 16.0f,
- 2 / 16.0f, 4 / 16.0f, 2 / 16.0f,
- 1 / 16.0f, 2 / 16.0f, 1 / 16.0f};
-
- const float *fp = soft;
- unsigned char color[4];
- float dx, dy;
-
- color[0] = color_in[0];
- color[1] = color_in[1];
- color[2] = color_in[2];
-
- const float alpha_in = (1 / 255.0f) * color_in[3];
-
- for (dx = -1; dx < 2; dx++) {
- for (dy = -1; dy < 2; dy++, fp++) {
- color[3] = FTOCHAR(*fp * alpha_in);
- blf_texture_draw(color, uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
- }
- }
+ float ofs[2] = { 1 / (float)tex_w, 1 / (float)tex_h };
+ float uv_flag[2][2];
+ copy_v4_v4((float *)uv_flag, (float *)uv);
+ /* flag the x component sign for 3x3 bluring */
+ uv_flag[0][0] = -(uv_flag[0][0] - ofs[0]);
+ uv_flag[0][1] = (uv_flag[0][1] - ofs[1]);
+ uv_flag[1][0] = -(uv_flag[1][0] + ofs[0]);
+ uv_flag[1][1] = (uv_flag[1][1] + ofs[1]);
+
+ blf_texture_draw(color_in, uv_flag, x1 - 1, y1 + 1, x2 + 1, y2 - 1);
}
static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y)
@@ -410,41 +438,43 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
if ((!g->width) || (!g->height))
return;
+ glActiveTexture(GL_TEXTURE0);
+
if (g->build_tex == 0) {
GlyphCacheBLF *gc = font->glyph_cache;
- if (font->max_tex_size == -1)
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&font->max_tex_size);
+ if (font->tex_size_max == -1)
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&font->tex_size_max);
- if (gc->cur_tex == BLF_CURTEX_UNSET) {
+ if (gc->texture_current == BLF_TEXTURE_UNSET) {
blf_glyph_cache_texture(font, gc);
- gc->x_offs = gc->pad;
- gc->y_offs = 0;
+ gc->offset_x = gc->pad;
+ gc->offset_y = 3; /* enough padding for blur */
}
- if (gc->x_offs > (gc->p2_width - gc->max_glyph_width)) {
- gc->x_offs = gc->pad;
- gc->y_offs += gc->max_glyph_height;
+ if (gc->offset_x > (gc->p2_width - gc->glyph_width_max)) {
+ gc->offset_x = gc->pad;
+ gc->offset_y += gc->glyph_height_max;
- if (gc->y_offs > (gc->p2_height - gc->max_glyph_height)) {
- gc->y_offs = 0;
+ if (gc->offset_y > (gc->p2_height - gc->glyph_height_max)) {
+ gc->offset_y = 3; /* enough padding for blur */
blf_glyph_cache_texture(font, gc);
}
}
- g->tex = gc->textures[gc->cur_tex];
- g->xoff = gc->x_offs;
- g->yoff = gc->y_offs;
+ g->tex = gc->textures[gc->texture_current];
+ g->offset_x = gc->offset_x;
+ g->offset_y = gc->offset_y;
/* prevent glTexSubImage2D from failing if the character
* asks for pixels out of bounds, this tends only to happen
* with very small sizes (5px high or less) */
- if (UNLIKELY((g->xoff + g->width) > gc->p2_width)) {
- g->width -= (g->xoff + g->width) - gc->p2_width;
+ if (UNLIKELY((g->offset_x + g->width) > gc->p2_width)) {
+ g->width -= (g->offset_x + g->width) - gc->p2_width;
BLI_assert(g->width > 0);
}
- if (UNLIKELY((g->yoff + g->height) > gc->p2_height)) {
- g->height -= (g->yoff + g->height) - gc->p2_height;
+ if (UNLIKELY((g->offset_y + g->height) > gc->p2_height)) {
+ g->height -= (g->offset_y + g->height) - gc->p2_height;
BLI_assert(g->height > 0);
}
@@ -459,21 +489,21 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, g->tex);
- glTexSubImage2D(GL_TEXTURE_2D, 0, g->xoff, g->yoff, g->width, g->height, GL_RED, GL_UNSIGNED_BYTE, g->bitmap);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, g->offset_x, g->offset_y, g->width, g->height, GL_RED, GL_UNSIGNED_BYTE, g->bitmap);
glPixelStorei(GL_UNPACK_LSB_FIRST, lsb_first);
glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
- g->uv[0][0] = ((float)g->xoff) / ((float)gc->p2_width);
- g->uv[0][1] = ((float)g->yoff) / ((float)gc->p2_height);
- g->uv[1][0] = ((float)(g->xoff + g->width)) / ((float)gc->p2_width);
- g->uv[1][1] = ((float)(g->yoff + g->height)) / ((float)gc->p2_height);
+ g->uv[0][0] = ((float)g->offset_x) / ((float)gc->p2_width);
+ g->uv[0][1] = ((float)g->offset_y) / ((float)gc->p2_height);
+ g->uv[1][0] = ((float)(g->offset_x + g->width)) / ((float)gc->p2_width);
+ g->uv[1][1] = ((float)(g->offset_y + g->height)) / ((float)gc->p2_height);
/* update the x offset for the next glyph. */
- gc->x_offs += (int)BLI_rctf_size_x(&g->box) + gc->pad;
+ gc->offset_x += (int)BLI_rctf_size_x(&g->box) + gc->pad;
- gc->rem_glyphs--;
+ gc->glyphs_len_free--;
g->build_tex = 1;
}
@@ -493,7 +523,7 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
glBindTexture(GL_TEXTURE_2D, (font->tex_bind_state = g->tex));
}
- /* TODO: blur & shadow in shader, single quad per glyph */
+ g_batch.tex_bind_state = g->tex;
if (font->flags & BLF_SHADOW) {
rctf rect_ofs;
@@ -505,20 +535,24 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
blf_texture_draw(font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
}
else if (font->shadow <= 4) {
- blf_texture3_draw(font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
+ blf_texture3_draw(font->shadow_color, font->glyph_cache->p2_width, font->glyph_cache->p2_height, g->uv,
+ rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
}
else {
- blf_texture5_draw(font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
+ blf_texture5_draw(font->shadow_color, font->glyph_cache->p2_width, font->glyph_cache->p2_height, g->uv,
+ rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
}
}
#if BLF_BLUR_ENABLE
switch (font->blur) {
case 3:
- blf_texture3_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ blf_texture3_draw(font->color, font->glyph_cache->p2_width, font->glyph_cache->p2_height, g->uv,
+ rect.xmin, rect.ymin, rect.xmax, rect.ymax);
break;
case 5:
- blf_texture5_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ blf_texture5_draw(font->color, font->glyph_cache->p2_width, font->glyph_cache->p2_height, g->uv,
+ rect.xmin, rect.ymin, rect.xmax, rect.ymax);
break;
default:
blf_texture_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index ba17e050399..b48bd2fbae7 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -37,10 +37,9 @@ struct GlyphBLF;
struct GlyphCacheBLF;
struct rctf;
-/* vertex attribute IDs (fixed IDs so we don't have to pass them around) */
-#define BLF_POS_ID 0
-#define BLF_COORD_ID 1
-#define BLF_COLOR_ID 2
+void blf_batch_draw_vao_clear(void);
+void blf_batch_draw_begin(struct FontBLF *font);
+void blf_batch_draw(void);
unsigned int blf_next_p2(unsigned int x);
unsigned int blf_hash(unsigned int val);
@@ -79,6 +78,10 @@ int blf_font_count_missing_chars(struct FontBLF *font, const char *str, const si
void blf_font_free(struct FontBLF *font);
+struct KerningCacheBLF *blf_kerning_cache_find(struct FontBLF *font);
+struct KerningCacheBLF *blf_kerning_cache_new(struct FontBLF *font);
+void blf_kerning_cache_clear(struct FontBLF *font);
+
struct GlyphCacheBLF *blf_glyph_cache_find(struct FontBLF *font, unsigned int size, unsigned int dpi);
struct GlyphCacheBLF *blf_glyph_cache_new(struct FontBLF *font);
void blf_glyph_cache_clear(struct FontBLF *font);
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index 9164a02b2cc..1d70980d33d 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -31,6 +31,36 @@
#ifndef __BLF_INTERNAL_TYPES_H__
#define __BLF_INTERNAL_TYPES_H__
+#include "../../../intern/gawain/gawain/gwn_vertex_buffer.h"
+
+#define BLF_BATCH_DRAW_LEN_MAX 2048 /* in glyph */
+
+typedef struct BatchBLF{
+ struct FontBLF *font; /* can only batch glyph from the same font */
+ struct Gwn_Batch *batch;
+ struct Gwn_VertBuf *verts;
+ struct Gwn_VertBufRaw pos_step, tex_step, col_step;
+ unsigned int pos_loc, tex_loc, col_loc;
+ unsigned int glyph_len;
+ float ofs[2]; /* copy of font->pos */
+ float mat[4][4]; /* previous call modelmatrix. */
+ bool enabled, active, simple_shader;
+ unsigned int tex_bind_state;
+} BatchBLF;
+
+extern BatchBLF g_batch;
+
+typedef struct KerningCacheBLF {
+ struct KerningCacheBLF *next, *prev;
+
+ /* kerning mode. */
+ FT_UInt mode;
+
+ /* only cache a ascii glyph pairs. Only store the x
+ * offset we are interested in, instead of the full FT_Vector. */
+ int table[0x80][0x80];
+} KerningCacheBLF;
+
typedef struct GlyphCacheBLF {
struct GlyphCacheBLF *next;
struct GlyphCacheBLF *prev;
@@ -51,33 +81,33 @@ typedef struct GlyphCacheBLF {
unsigned int *textures;
/* size of the array. */
- unsigned int ntex;
+ unsigned int textures_len;
/* and the last texture, aka. the current texture. */
- unsigned int cur_tex;
+ unsigned int texture_current;
/* like bftgl, we draw every glyph in a big texture, so this is the
* current position inside the texture.
*/
- int x_offs;
- int y_offs;
+ int offset_x;
+ int offset_y;
/* and the space from one to other. */
int pad;
/* and the bigger glyph in the font. */
- int max_glyph_width;
- int max_glyph_height;
+ int glyph_width_max;
+ int glyph_height_max;
/* next two integer power of two, to build the texture. */
int p2_width;
int p2_height;
/* number of glyphs in the font. */
- int num_glyphs;
+ int glyphs_len_max;
- /* number of glyphs that we load here. */
- int rem_glyphs;
+ /* number of glyphs not yet loaded (decreases every glyph loaded). */
+ int glyphs_len_free;
/* ascender and descender value. */
float ascender;
@@ -106,8 +136,8 @@ typedef struct GlyphBLF {
unsigned int tex;
/* position inside the texture where this glyph is store. */
- int xoff;
- int yoff;
+ int offset_x;
+ int offset_y;
/* Bitmap data, from freetype. Take care that this
* can be NULL.
@@ -130,7 +160,7 @@ typedef struct GlyphBLF {
float pos_y;
/* with value of zero mean that we need build the texture. */
- short build_tex;
+ char build_tex;
} GlyphBLF;
typedef struct FontBufInfoBLF {
@@ -211,7 +241,7 @@ typedef struct FontBLF {
unsigned int size;
/* max texture size. */
- int max_tex_size;
+ int tex_size_max;
/* cache current OpenGL texture to save calls into the API */
unsigned int tex_bind_state;
@@ -225,6 +255,12 @@ typedef struct FontBLF {
/* current glyph cache, size and dpi. */
GlyphCacheBLF *glyph_cache;
+ /* list of kerning cache for this font. */
+ ListBase kerning_caches;
+
+ /* current kerning cache for this font and kerning mode. */
+ KerningCacheBLF *kerning_cache;
+
/* freetype2 lib handle. */
FT_Library ft_lib;
@@ -234,6 +270,9 @@ typedef struct FontBLF {
/* freetype2 face. */
FT_Face face;
+ /* freetype kerning */
+ FT_UInt kerning_mode;
+
/* data for buffer usage (drawing into a texture buffer) */
FontBufInfoBLF buf_info;
} FontBLF;
@@ -246,6 +285,6 @@ typedef struct DirBLF {
char *path;
} DirBLF;
-#define BLF_CURTEX_UNSET ((unsigned int)-1)
+#define BLF_TEXTURE_UNSET ((unsigned int)-1)
#endif /* __BLF_INTERNAL_TYPES_H__ */
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 9bb44a726de..4ae11b5cca5 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -165,7 +165,7 @@ typedef enum DMDirtyFlag {
DM_DIRTY_TESS_CDLAYERS = 1 << 0,
/* One of the MCOL layers have been updated, force updating of GPUDrawObject's colors buffer.
* This is necessary with modern, VBO draw code, as e.g. in vpaint mode me->mcol may be updated
- * without actually rebuilding dm (hence by defautl keeping same GPUDrawObject, and same colors
+ * without actually rebuilding dm (hence by default keeping same GPUDrawObject, and same colors
* buffer, which prevents update during a stroke!). */
DM_DIRTY_MCOL_UPDATE_DRAW = 1 << 1,
diff --git a/source/blender/blenkernel/BKE_addon.h b/source/blender/blenkernel/BKE_addon.h
index 74c1edd1c1b..e631d1d6537 100644
--- a/source/blender/blenkernel/BKE_addon.h
+++ b/source/blender/blenkernel/BKE_addon.h
@@ -26,8 +26,11 @@
* \ingroup bke
*/
-#include "RNA_types.h"
+struct ListBase;
+struct bAddon;
+
+#ifdef __RNA_TYPES_H__
typedef struct bAddonPrefType {
/* type info */
char idname[64]; // best keep the same size as BKE_ST_MAXNAME
@@ -36,6 +39,10 @@ typedef struct bAddonPrefType {
ExtensionRNA ext;
} bAddonPrefType;
+#else
+typedef struct bAddonPrefType bAddonPrefType;
+#endif
+
bAddonPrefType *BKE_addon_pref_type_find(const char *idname, bool quiet);
void BKE_addon_pref_type_add(bAddonPrefType *apt);
void BKE_addon_pref_type_remove(const bAddonPrefType *apt);
@@ -43,4 +50,8 @@ void BKE_addon_pref_type_remove(const bAddonPrefType *apt);
void BKE_addon_pref_type_init(void);
void BKE_addon_pref_type_free(void);
+struct bAddon *BKE_addon_new(void);
+struct bAddon *BKE_addon_ensure(struct ListBase *addons, const char *module);
+void BKE_addon_free(struct bAddon *addon);
+
#endif /* __BKE_ADDON_H__ */
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 192690c074c..bf37224c85f 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -171,41 +171,39 @@ void BKE_splineik_execute_tree(
void BKE_pose_eval_init(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
- struct Object *ob,
- struct bPose *pose);
+ struct Object *ob);
void BKE_pose_eval_init_ik(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
- struct Object *ob,
- struct bPose *pose);
+ struct Object *ob);
void BKE_pose_eval_bone(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
- struct bPoseChannel *pchan);
+ int pchan_index);
void BKE_pose_constraints_evaluate(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
- struct bPoseChannel *pchan);
+ int pchan_index);
void BKE_pose_bone_done(const struct EvaluationContext *eval_ctx,
- struct bPoseChannel *pchan);
+ struct Object *ob,
+ int pchan_index);
void BKE_pose_iktree_evaluate(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
- struct bPoseChannel *rootchan);
+ int rootchan_index);
void BKE_pose_splineik_evaluate(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
- struct bPoseChannel *rootchan);
+ int rootchan_index);
void BKE_pose_eval_flush(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
- struct Object *ob,
- struct bPose *pose);
+ struct Object *ob);
void BKE_pose_eval_proxy_copy(const struct EvaluationContext *eval_ctx,
struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_blender_undo.h b/source/blender/blenkernel/BKE_blender_undo.h
index 84a6d07be7d..a96f8af1fdb 100644
--- a/source/blender/blenkernel/BKE_blender_undo.h
+++ b/source/blender/blenkernel/BKE_blender_undo.h
@@ -31,22 +31,13 @@ extern "C" {
struct bContext;
struct Scene;
struct Main;
+struct MemFileUndoData;
#define BKE_UNDO_STR_MAX 64
-/* global undo */
-extern void BKE_undo_write(struct bContext *C, const char *name);
-extern void BKE_undo_step(struct bContext *C, int step);
-extern void BKE_undo_name(struct bContext *C, const char *name);
-extern bool BKE_undo_is_valid(const char *name);
-extern void BKE_undo_reset(void);
-extern void BKE_undo_number(struct bContext *C, int nr);
-extern const char *BKE_undo_get_name(int nr, bool *r_active);
-extern const char *BKE_undo_get_name_last(void);
-extern bool BKE_undo_save_file(const char *filename);
-extern struct Main *BKE_undo_get_main(struct Scene **r_scene);
-
-extern void BKE_undo_callback_wm_kill_jobs_set(void (*callback)(struct bContext *C));
+struct MemFileUndoData *BKE_memfile_undo_encode(struct Main *bmain, struct MemFileUndoData *mfu_prev);
+bool BKE_memfile_undo_decode(struct MemFileUndoData *mfu, struct bContext *C);
+void BKE_memfile_undo_free(struct MemFileUndoData *mfu);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index ceb466ebdcd..901f9e6d3ac 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -28,7 +28,7 @@
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 280
-#define BLENDER_SUBVERSION 4
+#define BLENDER_SUBVERSION 5
/* Several breakages with 270, e.g. constraint deg vs rad */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 6
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index e7af7400850..f2601f2ca32 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -36,6 +36,7 @@ struct Scene;
struct UnifiedPaintSettings;
// enum eCurveMappingPreset;
+#include "DNA_object_enums.h"
/* globals for brush execution */
void BKE_brush_system_init(void);
@@ -43,8 +44,8 @@ void BKE_brush_system_exit(void);
/* datablock functions */
void BKE_brush_init(struct Brush *brush);
-struct Brush *BKE_brush_add(struct Main *bmain, const char *name, short ob_mode);
-struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode);
+struct Brush *BKE_brush_add(struct Main *bmain, const char *name, const eObjectMode ob_mode);
+struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode);
void BKE_brush_copy_data(struct Main *bmain, struct Brush *brush_dst, const struct Brush *brush_src, const int flag);
struct Brush *BKE_brush_copy(struct Main *bmain, const struct Brush *brush);
void BKE_brush_make_local(struct Main *bmain, struct Brush *brush, const bool lib_local);
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index 7f7cbd678e2..8923edacb07 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -236,7 +236,8 @@ void bvhtree_update_from_cloth(struct ClothModifierData *clmd, bool moving);
void bvhselftree_update_from_cloth(struct ClothModifierData *clmd, bool moving);
// needed for button_object.c
-void cloth_clear_cache (struct Object *ob, struct ClothModifierData *clmd, float framenr );
+void cloth_clear_cache(
+ struct Object *ob, struct ClothModifierData *clmd, float framenr );
void cloth_parallel_transport_hair_frame(float mat[3][3], const float dir_old[3], const float dir_new[3]);
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index 48b4ff881ae..d3a4d2b8d5b 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -44,19 +44,27 @@ struct Main;
struct Object;
struct Scene;
struct SceneCollection;
+struct ViewLayer;
struct SceneCollection *BKE_collection_add(
struct ID *owner_id, struct SceneCollection *sc_parent, const int type, const char *name);
bool BKE_collection_remove(struct ID *owner_id, struct SceneCollection *sc);
void BKE_collection_copy_data(struct SceneCollection *sc_dst, struct SceneCollection *sc_src, const int flag);
+struct SceneCollection *BKE_collection_duplicate(struct ID *owner_id, struct SceneCollection *scene_collection);
struct SceneCollection *BKE_collection_master(const struct ID *owner_id);
-void BKE_collection_rename(const struct Scene *scene, struct SceneCollection *sc, const char *name);
+void BKE_collection_rename(const struct ID *owner_id, struct SceneCollection *sc, const char *name);
void BKE_collection_master_free(struct ID *owner_id, const bool do_id_user);
bool BKE_collection_object_add(const struct ID *owner_id, struct SceneCollection *sc, struct Object *object);
void BKE_collection_object_add_from(struct Scene *scene, struct Object *ob_src, struct Object *ob_dst);
bool BKE_collection_object_remove(struct Main *bmain, struct ID *owner_id, struct SceneCollection *sc, struct Object *object, const bool free_us);
bool BKE_collections_object_remove(struct Main *bmain, struct ID *owner_id, struct Object *object, const bool free_us);
void BKE_collection_object_move(struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src, struct Object *ob);
+bool BKE_collection_object_exists(struct SceneCollection *scene_collection, struct Object *ob);
+struct SceneCollection *BKE_collection_from_index(struct Scene *scene, const int index);
+
+void BKE_collection_new_name_get(struct ID *owner_id, struct SceneCollection *sc_parent, char *rname);
+
+bool BKE_collection_objects_select(struct ViewLayer *view_layer, struct SceneCollection *scene_collection);
struct Group *BKE_collection_group_create(struct Main *bmain, struct Scene *scene, struct LayerCollection *lc);
@@ -82,7 +90,7 @@ void BKE_scene_objects_iterator_begin(struct BLI_Iterator *iter, void *data_in);
void BKE_scene_objects_iterator_next(struct BLI_Iterator *iter);
void BKE_scene_objects_iterator_end(struct BLI_Iterator *iter);
-#define FOREACH_SCENE_COLLECTION(_id, _instance) \
+#define FOREACH_SCENE_COLLECTION_BEGIN(_id, _instance) \
ITER_BEGIN(BKE_scene_collections_iterator_begin, \
BKE_scene_collections_iterator_next, \
BKE_scene_collections_iterator_end, \
@@ -91,7 +99,7 @@ void BKE_scene_objects_iterator_end(struct BLI_Iterator *iter);
#define FOREACH_SCENE_COLLECTION_END \
ITER_END
-#define FOREACH_SCENE_OBJECT(scene, _instance) \
+#define FOREACH_SCENE_OBJECT_BEGIN(scene, _instance) \
ITER_BEGIN(BKE_scene_objects_iterator_begin, \
BKE_scene_objects_iterator_next, \
BKE_scene_objects_iterator_end, \
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 6b88df8b203..947ed7cd600 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -77,6 +77,8 @@ struct SpaceClip;
struct ID;
struct EvaluationContext;
+#include "DNA_object_enums.h"
+
/* Structs */
struct bContext;
@@ -261,7 +263,9 @@ struct RenderEngineType *CTX_data_engine_type(const bContext *C);
struct ToolSettings *CTX_data_tool_settings(const bContext *C);
const char *CTX_data_mode_string(const bContext *C);
-int CTX_data_mode_enum_ex(const struct Object *obedit, const struct Object *ob);
+int CTX_data_mode_enum_ex(
+ const struct Object *obedit, const struct Object *ob,
+ const eObjectMode object_mode);
int CTX_data_mode_enum(const bContext *C);
void CTX_data_main_set(bContext *C, struct Main *bmain);
diff --git a/source/blender/blenkernel/BKE_editlattice.h b/source/blender/blenkernel/BKE_editlattice.h
new file mode 100644
index 00000000000..476cf535e97
--- /dev/null
+++ b/source/blender/blenkernel/BKE_editlattice.h
@@ -0,0 +1,34 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file BKE_editlattice.h
+ * \ingroup bke
+ */
+
+#ifndef __BKE_EDITLATTICE_H__
+#define __BKE_EDITLATTICE_H__
+
+struct Object;
+
+void BKE_editlattice_free(struct Object *ob);
+void BKE_editlattice_make(struct Object *obedit);
+void BKE_editlattice_load(struct Object *obedit);
+
+#endif /* __BKE_EDITLATTICE_H__ */
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index 80a8f750d20..c1b437661c5 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -80,6 +80,13 @@ typedef struct Global {
* however this is now only used for runtime options */
int f;
+ struct {
+ /* Logging vars (different loggers may use). */
+ int level;
+ /* FILE handle or use stderr (we own this so close when done). */
+ void *file;
+ } log;
+
/* debug flag, G_DEBUG, G_DEBUG_PYTHON & friends, set python or command line args */
int debug;
@@ -122,13 +129,21 @@ enum {
G_DEBUG_WM = (1 << 5), /* operator, undo */
G_DEBUG_JOBS = (1 << 6), /* jobs time profiling */
G_DEBUG_FREESTYLE = (1 << 7), /* freestyle messages */
- G_DEBUG_DEPSGRAPH = (1 << 8), /* depsgraph messages */
- G_DEBUG_SIMDATA = (1 << 9), /* sim debug data display */
- G_DEBUG_GPU_MEM = (1 << 10), /* gpu memory in status bar */
- G_DEBUG_DEPSGRAPH_NO_THREADS = (1 << 11), /* single threaded depsgraph */
- G_DEBUG_GPU = (1 << 12), /* gpu debug */
- G_DEBUG_IO = (1 << 13), /* IO Debugging (for Collada, ...)*/
- G_DEBUG_GPU_SHADERS = (1 << 14), /* GLSL shaders */
+ G_DEBUG_DEPSGRAPH_BUILD = (1 << 8), /* depsgraph construction messages */
+ G_DEBUG_DEPSGRAPH_EVAL = (1 << 9), /* depsgraph evaluation messages */
+ G_DEBUG_DEPSGRAPH_TAG = (1 << 10), /* depsgraph tagging messages */
+ G_DEBUG_DEPSGRAPH_TIME = (1 << 11), /* depsgraph timing statistics and messages */
+ G_DEBUG_DEPSGRAPH_NO_THREADS = (1 << 12), /* single threaded depsgraph */
+ G_DEBUG_DEPSGRAPH_PRETTY = (1 << 13), /* use pretty colors in depsgraph messages */
+ G_DEBUG_DEPSGRAPH = (G_DEBUG_DEPSGRAPH_BUILD |
+ G_DEBUG_DEPSGRAPH_EVAL |
+ G_DEBUG_DEPSGRAPH_TAG |
+ G_DEBUG_DEPSGRAPH_TIME),
+ G_DEBUG_SIMDATA = (1 << 14), /* sim debug data display */
+ G_DEBUG_GPU_MEM = (1 << 15), /* gpu memory in status bar */
+ G_DEBUG_GPU = (1 << 16), /* gpu debug */
+ G_DEBUG_IO = (1 << 17), /* IO Debugging (for Collada, ...)*/
+ G_DEBUG_GPU_SHADERS = (1 << 18), /* GLSL shaders */
};
#define G_DEBUG_ALL (G_DEBUG | G_DEBUG_FFMPEG | G_DEBUG_PYTHON | G_DEBUG_EVENTS | G_DEBUG_WM | G_DEBUG_JOBS | \
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
index 74255cfc941..a842bec7609 100644
--- a/source/blender/blenkernel/BKE_group.h
+++ b/source/blender/blenkernel/BKE_group.h
@@ -62,7 +62,7 @@ void BKE_group_eval_view_layers(const struct EvaluationContext *eval_ctx,
/* Helper macros. */
-#define FOREACH_GROUP_BASE(_group, _base) \
+#define FOREACH_GROUP_BASE_BEGIN(_group, _base) \
for (Base *_base = (Base *)(_group)->view_layer->object_bases.first; \
_base; \
_base = _base->next) \
@@ -71,7 +71,7 @@ void BKE_group_eval_view_layers(const struct EvaluationContext *eval_ctx,
#define FOREACH_GROUP_BASE_END \
}
-#define FOREACH_GROUP_OBJECT(_group, _object) \
+#define FOREACH_GROUP_OBJECT_BEGIN(_group, _object) \
for (Base *_base = (Base *)(_group)->view_layer->object_bases.first; \
_base; \
_base = _base->next) \
@@ -80,6 +80,6 @@ void BKE_group_eval_view_layers(const struct EvaluationContext *eval_ctx,
BLI_assert(_object != NULL);
#define FOREACH_GROUP_OBJECT_END \
- }
+ } ((void)0)
#endif /* __BKE_GROUP_H__ */
diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h
index 39e6b145755..a9ca5cc8bbb 100644
--- a/source/blender/blenkernel/BKE_icons.h
+++ b/source/blender/blenkernel/BKE_icons.h
@@ -58,19 +58,19 @@ int BKE_icon_id_ensure(struct ID *id);
int BKE_icon_preview_ensure(struct ID *id, struct PreviewImage *preview);
/* retrieve icon for id */
-struct Icon *BKE_icon_get(int icon_id);
+struct Icon *BKE_icon_get(const int icon_id);
/* set icon for id if not already defined */
/* used for inserting the internal icons */
-void BKE_icon_set(int icon_id, struct Icon *icon);
+void BKE_icon_set(const int icon_id, struct Icon *icon);
/* remove icon and free data if library object becomes invalid */
void BKE_icon_id_delete(struct ID *id);
-void BKE_icon_delete(int icon_id);
+void BKE_icon_delete(const int icon_id);
/* report changes - icon needs to be recalculated */
-void BKE_icon_changed(int icon_id);
+void BKE_icon_changed(const int icon_id);
/* free all icons */
void BKE_icons_free(void);
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 57459412efc..1af123759e6 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -67,6 +67,11 @@ void BKE_image_init(struct Image *image);
typedef void (StampCallback)(void *data, const char *propname, char *propvalue, int len);
void BKE_render_result_stamp_info(struct Scene *scene, struct Object *camera, struct RenderResult *rr, bool allocate_only);
+/**
+ * Fills in the static stamp data (i.e. everything except things that can change per frame).
+ * The caller is responsible for freeing the allocated memory.
+ */
+struct StampData *BKE_stamp_info_from_scene_static(struct Scene *scene);
void BKE_imbuf_stamp_info(struct RenderResult *rr, struct ImBuf *ibuf);
void BKE_stamp_info_from_imbuf(struct RenderResult *rr, struct ImBuf *ibuf);
void BKE_stamp_info_callback(void *data, struct StampData *stamp_data, StampCallback callback, bool noskip);
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index b605b208f66..9c06ae4f40d 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -29,6 +29,8 @@
#include "BKE_collection.h"
+#include "DNA_scene_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -76,11 +78,18 @@ struct Base *BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Objec
void BKE_view_layer_base_deselect_all(struct ViewLayer *view_layer);
void BKE_view_layer_base_select(struct ViewLayer *view_layer, struct Base *selbase);
+void BKE_layer_collection_sync_flags(
+ struct ID *owner_id,
+ struct SceneCollection *scene_collection_dst,
+ struct SceneCollection *scene_collection_src);
+
void BKE_view_layer_copy_data(
struct ViewLayer *view_layer_dst, struct ViewLayer *view_layer_src,
struct SceneCollection *mc_dst, struct SceneCollection *mc_src,
const int flag);
+struct LayerCollection *BKE_layer_collection_duplicate(struct ID *owner_id, struct LayerCollection *layer_collection);
+
void BKE_layer_collection_free(struct ViewLayer *view_layer, struct LayerCollection *lc);
struct LayerCollection *BKE_layer_collection_get_active(struct ViewLayer *view_layer);
@@ -103,9 +112,12 @@ void BKE_collection_unlink(struct ViewLayer *view_layer, struct LayerCollection
void BKE_collection_enable(struct ViewLayer *view_layer, struct LayerCollection *lc);
+struct LayerCollection *BKE_layer_collection_first_from_scene_collection(struct ViewLayer *view_layer, const struct SceneCollection *scene_collection);
bool BKE_view_layer_has_collection(struct ViewLayer *view_layer, const struct SceneCollection *sc);
bool BKE_scene_has_object(struct Scene *scene, struct Object *ob);
+void BKE_layer_collection_objects_select(struct LayerCollection *layer_collection);
+
/* syncing */
void BKE_layer_sync_new_scene_collection(struct ID *owner_id, const struct SceneCollection *sc_parent, struct SceneCollection *sc);
@@ -157,14 +169,13 @@ void BKE_collection_engine_property_value_set_bool(struct IDProperty *props, con
/* evaluation */
-void BKE_layer_eval_layer_collection_pre(const struct EvaluationContext *eval_ctx,
- struct ID *owner_id,
- struct ViewLayer *view_layer);
-void BKE_layer_eval_layer_collection(const struct EvaluationContext *eval_ctx,
- struct LayerCollection *layer_collection,
- struct LayerCollection *parent_layer_collection);
-void BKE_layer_eval_layer_collection_post(const struct EvaluationContext *eval_ctx,
- struct ViewLayer *view_layer);
+void BKE_layer_eval_view_layer(const struct EvaluationContext *eval_ctx,
+ struct ID *owner_id,
+ struct ViewLayer *view_layer);
+
+void BKE_layer_eval_view_layer_indexed(const struct EvaluationContext *eval_ctx,
+ struct ID *owner_id,
+ int view_layer_index);
/* iterators */
@@ -188,7 +199,7 @@ void BKE_visible_bases_iterator_begin(BLI_Iterator *iter, void *data_in);
void BKE_visible_bases_iterator_next(BLI_Iterator *iter);
void BKE_visible_bases_iterator_end(BLI_Iterator *iter);
-#define FOREACH_SELECTED_OBJECT(view_layer, _instance) \
+#define FOREACH_SELECTED_OBJECT_BEGIN(view_layer, _instance) \
ITER_BEGIN(BKE_selected_objects_iterator_begin, \
BKE_selected_objects_iterator_next, \
BKE_selected_objects_iterator_end, \
@@ -197,7 +208,7 @@ void BKE_visible_bases_iterator_end(BLI_Iterator *iter);
#define FOREACH_SELECTED_OBJECT_END \
ITER_END
-#define FOREACH_VISIBLE_OBJECT(view_layer, _instance) \
+#define FOREACH_VISIBLE_OBJECT_BEGIN(view_layer, _instance) \
ITER_BEGIN(BKE_visible_objects_iterator_begin, \
BKE_visible_objects_iterator_next, \
BKE_visible_objects_iterator_end, \
@@ -206,7 +217,7 @@ void BKE_visible_bases_iterator_end(BLI_Iterator *iter);
#define FOREACH_VISIBLE_OBJECT_END \
ITER_END
-#define FOREACH_SELECTED_BASE(view_layer, _instance) \
+#define FOREACH_SELECTED_BASE_BEGIN(view_layer, _instance) \
ITER_BEGIN(BKE_selected_bases_iterator_begin, \
BKE_selected_bases_iterator_next, \
BKE_selected_bases_iterator_end, \
@@ -215,7 +226,7 @@ void BKE_visible_bases_iterator_end(BLI_Iterator *iter);
#define FOREACH_SELECTED_BASE_END \
ITER_END
-#define FOREACH_VISIBLE_BASE(view_layer, _instance) \
+#define FOREACH_VISIBLE_BASE_BEGIN(view_layer, _instance) \
ITER_BEGIN(BKE_visible_bases_iterator_begin, \
BKE_visible_bases_iterator_next, \
BKE_visible_bases_iterator_end, \
@@ -225,18 +236,18 @@ void BKE_visible_bases_iterator_end(BLI_Iterator *iter);
ITER_END
-#define FOREACH_OBJECT(view_layer, _instance) \
+#define FOREACH_OBJECT_BEGIN(view_layer, _instance) \
{ \
Object *_instance; \
- Base *base; \
- for (base = (view_layer)->object_bases.first; base; base = base->next) { \
- _instance = base->object;
+ Base *_base; \
+ for (_base = (view_layer)->object_bases.first; _base; _base = _base->next) { \
+ _instance = _base->object;
#define FOREACH_OBJECT_END \
} \
-}
+} ((void)0)
-#define FOREACH_OBJECT_FLAG(scene, view_layer, flag, _instance) \
+#define FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, flag, _instance) \
{ \
IteratorBeginCb func_begin; \
IteratorCb func_next, func_end; \
@@ -258,21 +269,24 @@ void BKE_visible_bases_iterator_end(BLI_Iterator *iter);
#define FOREACH_OBJECT_FLAG_END \
- ITER_END \
-}
+ ITER_END; \
+} ((void)0)
-typedef struct ObjectsRenderableIteratorData {
+struct ObjectsRenderableIteratorData {
struct Scene *scene;
+ struct Base base_temp;
+ struct Scene scene_temp;
struct {
struct ViewLayer *view_layer;
struct Base *base;
struct Scene *set;
} iter;
-} ObjectsRenderableIteratorData;
+};
-#define FOREACH_OBJECT_RENDERABLE(scene_, _instance) \
- ObjectsRenderableIteratorData data_ = { \
+#define FOREACH_OBJECT_RENDERABLE_BEGIN(scene_, _instance) \
+{ \
+ struct ObjectsRenderableIteratorData data_ = { \
.scene = (scene_), \
}; \
ITER_BEGIN(BKE_renderable_objects_iterator_begin, \
@@ -282,7 +296,8 @@ typedef struct ObjectsRenderableIteratorData {
#define FOREACH_OBJECT_RENDERABLE_END \
- ITER_END
+ ITER_END; \
+} ((void)0)
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index d905f03a5ee..3e767e85142 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -84,10 +84,12 @@ typedef struct Main {
short minversionfile, minsubversionfile;
uint64_t build_commit_timestamp; /* commit's timestamp from buildinfo */
char build_hash[16]; /* hash from buildinfo */
- short recovered; /* indicate the main->name (file) is the recovered one */
+ char recovered; /* indicate the main->name (file) is the recovered one */
+ /** All current ID's exist in the last memfile undo step. */
+ char is_memfile_undo_written;
BlendThumbnail *blen_thumb;
-
+
struct Library *curlib;
ListBase scene;
ListBase library;
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index 9db277f95fb..d4776d890d2 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -77,9 +77,9 @@ void BKE_mball_eval_geometry(const struct EvaluationContext *eval_ctx,
struct MetaBall *mball);
/* Draw Cache */
-void BKE_mball_element_calc_display_m3x4(float r_scale_xform[3][4],
- const float obmat[4][4],
- const float local_pos[3]);
+void BKE_mball_element_calc_scale_xform(float r_scale_xform[3][4],
+ const float obmat[4][4],
+ const float local_pos[3]);
enum {
BKE_MBALL_BATCH_DIRTY_ALL = 0,
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 5ee3b9be5f9..79d72206903 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -141,7 +141,7 @@ 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);
struct Mesh *BKE_mesh_new_from_object(const struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce, struct Object *ob,
- int apply_modifiers, int settings, int calc_tessface, int calc_undeformed);
+ int apply_modifiers, int calc_tessface, int calc_undeformed);
/* vertex level transformations & checks (no derived mesh) */
@@ -193,6 +193,24 @@ void BKE_mesh_calc_normals_looptri(
const struct MLoop *mloop,
const struct MLoopTri *looptri, int looptri_num,
float (*r_tri_nors)[3]);
+void BKE_mesh_loop_tangents_ex(
+ const struct MVert *mverts, const int numVerts, const struct MLoop *mloops,
+ float (*r_looptangent)[4], float (*loopnors)[3], const struct MLoopUV *loopuv,
+ const int numLoops, const struct MPoly *mpolys, const int numPolys,
+ struct ReportList *reports);
+void BKE_mesh_loop_tangents(
+ struct Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], struct ReportList *reports);
+void BKE_mesh_loop_manifold_fan_around_vert_next(
+ const struct MLoop *mloops, const struct MPoly *mpolys,
+ const int *loop_to_poly, const int *e2lfan_curr, const uint mv_pivot_index,
+ const struct MLoop **r_mlfan_curr, int *r_mlfan_curr_index, int *r_mlfan_vert_index, int *r_mpfan_curr_index);
+
+void BKE_edges_sharp_from_angle_set(
+ const struct MVert *mverts, const int numVerts,
+ struct MEdge *medges, const int numEdges,
+ struct MLoop *mloops, const int numLoops,
+ struct MPoly *mpolys, const float (*polynors)[3], const int numPolys,
+ const float split_angle);
/**
* References a contiguous loop-fan with normal offset vars.
@@ -203,17 +221,38 @@ typedef struct MLoopNorSpace {
float vec_ortho[3]; /* Third vector, orthogonal to vec_lnor and vec_ref. */
float ref_alpha; /* Reference angle, around vec_ortho, in ]0, pi] range (0.0 marks that space as invalid). */
float ref_beta; /* Reference angle, around vec_lnor, in ]0, 2pi] range (0.0 marks that space as invalid). */
- struct LinkNode *loops; /* All indices (uint_in_ptr) of loops using this lnor space (i.e. smooth fan of loops). */
+ /* All loops using this lnor space (i.e. smooth fan of loops),
+ * as (depending on owning MLoopNorSpaceArrary.data_type):
+ * - Indices (uint_in_ptr), or
+ * - BMLoop pointers. */
+ struct LinkNode *loops;
+ char flags;
} MLoopNorSpace;
/**
+ * MLoopNorSpace.flags
+ */
+enum {
+ MLNOR_SPACE_IS_SINGLE = 1 << 0,
+};
+
+/**
* Collection of #MLoopNorSpace basic storage & pre-allocation.
*/
typedef struct MLoopNorSpaceArray {
MLoopNorSpace **lspacearr; /* MLoop aligned array */
struct LinkNode *loops_pool; /* Allocated once, avoids to call BLI_linklist_prepend_arena() for each loop! */
+ char data_type; /* Whether we store loop indices, or pointers to BMLoop. */
struct MemArena *mem;
} MLoopNorSpaceArray;
-void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoops);
+/**
+ * MLoopNorSpaceArray.data_type
+ */
+enum {
+ MLNOR_SPACEARR_LOOP_INDEX = 0,
+ MLNOR_SPACEARR_BMLOOP_PTR = 1,
+};
+
+void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoops, const char data_type);
void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr);
void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr);
MLoopNorSpace *BKE_lnor_space_create(MLoopNorSpaceArray *lnors_spacearr);
@@ -221,7 +260,8 @@ void BKE_lnor_space_define(
MLoopNorSpace *lnor_space, const float lnor[3], float vec_ref[3], float vec_other[3],
struct BLI_Stack *edge_vectors);
void BKE_lnor_space_add_loop(
- MLoopNorSpaceArray *lnors_spacearr, MLoopNorSpace *lnor_space, const int ml_index, const bool add_to_list);
+ MLoopNorSpaceArray *lnors_spacearr, MLoopNorSpace *lnor_space,
+ const int ml_index, void *bm_loop, const bool is_single);
void BKE_lnor_space_custom_data_to_normal(MLoopNorSpace *lnor_space, const short clnor_data[2], float r_custom_lnor[3]);
void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space, const float custom_lnor[3], short r_clnor_data[2]);
@@ -234,7 +274,7 @@ void BKE_mesh_normals_loop_split(
const struct MVert *mverts, const int numVerts, struct MEdge *medges, const int numEdges,
struct MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
struct MPoly *mpolys, const float (*polynors)[3], const int numPolys,
- const bool use_split_normals, float split_angle,
+ const bool use_split_normals, const float split_angle,
MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], int *r_loop_to_poly);
void BKE_mesh_normals_loop_custom_set(
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 451823aedf5..329defbc77c 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -34,8 +34,6 @@
struct ID;
struct DerivedMesh;
-struct DagForest;
-struct DagNode;
struct EvaluationContext;
struct Object;
struct Scene;
@@ -129,6 +127,12 @@ typedef enum ModifierApplyFlag {
} ModifierApplyFlag;
+typedef struct ModifierUpdateDepsgraphContext {
+ struct Scene *scene;
+ struct Object *object;
+ struct DepsNodeHandle *node;
+} ModifierUpdateDepsgraphContext;
+
typedef struct ModifierTypeInfo {
/* The user visible name for this modifier */
char name[32];
@@ -268,11 +272,8 @@ typedef struct ModifierTypeInfo {
* This function is optional.
*/
void (*updateDepsgraph)(struct ModifierData *md,
- struct Main *bmain,
- struct Scene *scene,
- struct Object *ob,
- struct DepsNodeHandle *node);
-
+ const ModifierUpdateDepsgraphContext *ctx);
+
/* Should return true if the modifier needs to be recalculated on time
* changes.
*
@@ -331,6 +332,7 @@ const ModifierTypeInfo *modifierType_getInfo(ModifierType type);
* default values if pointer is optional.
*/
struct ModifierData *modifier_new(int type);
+void modifier_free_ex(struct ModifierData *md, const int flag);
void modifier_free(struct ModifierData *md);
bool modifier_unique_name(struct ListBase *modifiers, struct ModifierData *md);
diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h
index bd193b82b9e..818f79ad8ac 100644
--- a/source/blender/blenkernel/BKE_movieclip.h
+++ b/source/blender/blenkernel/BKE_movieclip.h
@@ -60,6 +60,7 @@ struct ImBuf *BKE_movieclip_get_ibuf_flag(struct MovieClip *clip, struct MovieCl
void BKE_movieclip_get_size(struct MovieClip *clip, struct MovieClipUser *user, int *width, int *height);
void BKE_movieclip_get_size_fl(struct MovieClip *clip, struct MovieClipUser *user, float size[2]);
int BKE_movieclip_get_duration(struct MovieClip *clip);
+float BKE_movieclip_get_fps(struct MovieClip *clip);
void BKE_movieclip_get_aspect(struct MovieClip *clip, float *aspx, float *aspy);
bool BKE_movieclip_has_frame(struct MovieClip *clip, struct MovieClipUser *user);
void BKE_movieclip_user_set_frame(struct MovieClipUser *user, int framenr);
diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h
index 8d9fc8ff6cf..4509d374b02 100644
--- a/source/blender/blenkernel/BKE_nla.h
+++ b/source/blender/blenkernel/BKE_nla.h
@@ -46,18 +46,18 @@ struct PropertyRNA;
/* ----------------------------- */
/* Data Management */
-void free_nlastrip(ListBase *strips, struct NlaStrip *strip);
-void free_nlatrack(ListBase *tracks, struct NlaTrack *nlt);
-void free_nladata(ListBase *tracks);
-
-struct NlaStrip *copy_nlastrip(struct NlaStrip *strip, const bool use_same_action);
-struct NlaTrack *copy_nlatrack(struct NlaTrack *nlt, const bool use_same_actions);
-void copy_nladata(ListBase *dst, ListBase *src);
-
-struct NlaTrack *add_nlatrack(struct AnimData *adt, struct NlaTrack *prev);
-struct NlaStrip *add_nlastrip(struct bAction *act);
-struct NlaStrip *add_nlastrip_to_stack(struct AnimData *adt, struct bAction *act);
-struct NlaStrip *add_nla_soundstrip(struct Scene *scene, struct Speaker *spk);
+void BKE_nlastrip_free(ListBase *strips, struct NlaStrip *strip);
+void BKE_nlatrack_free(ListBase *tracks, struct NlaTrack *nlt);
+void BKE_nla_tracks_free(ListBase *tracks);
+
+struct NlaStrip *BKE_nlastrip_copy(struct NlaStrip *strip, const bool use_same_action);
+struct NlaTrack *BKE_nlatrack_copy(struct NlaTrack *nlt, const bool use_same_actions);
+void BKE_nla_tracks_copy(ListBase *dst, ListBase *src);
+
+struct NlaTrack *BKE_nlatrack_add(struct AnimData *adt, struct NlaTrack *prev);
+struct NlaStrip *BKE_nlastrip_new(struct bAction *act);
+struct NlaStrip *BKE_nlastack_add_strip(struct AnimData *adt, struct bAction *act);
+struct NlaStrip *BKE_nla_add_soundstrip(struct Scene *scene, struct Speaker *spk);
/* ----------------------------- */
/* API */
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 4e30cb076d4..6427a87a182 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -575,7 +575,6 @@ void BKE_node_preview_set_pixel(struct bNodePreview *preview, const f
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Node Type Access
* \{ */
@@ -605,6 +604,7 @@ void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpufu
void node_type_internal_links(struct bNodeType *ntype, void (*update_internal_links)(struct bNodeTree *, struct bNode *));
void node_type_compatibility(struct bNodeType *ntype, short compatibility);
+/** \} */
/* -------------------------------------------------------------------- */
/** \name Node Generic Functions
@@ -701,7 +701,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, c
/* -------------------------------------------------------------------- */
/** \name Shader Nodes
- */
+ * \{ */
struct ShadeInput;
struct ShadeResult;
@@ -801,6 +801,8 @@ struct ShadeResult;
#define SH_NODE_EEVEE_SPECULAR 195
#define SH_NODE_BEVEL 197
#define SH_NODE_DISPLACEMENT 198
+#define SH_NODE_VECTOR_DISPLACEMENT 199
+#define SH_NODE_VOLUME_PRINCIPLED 200
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
@@ -825,7 +827,7 @@ void ntreeGPUMaterialDomain(struct bNodeTree *ntree, bool *has_surfac
/* -------------------------------------------------------------------- */
/** \name Composite Nodes
- */
+ * \{ */
/* output socket defines */
#define RRES_OUT_IMAGE 0
@@ -1009,7 +1011,7 @@ void ntreeCompositColorBalanceSyncFromCDL(bNodeTree *ntree, bNode *node);
/* -------------------------------------------------------------------- */
/** \name Texture Nodes
- */
+ * \{ */
struct TexResult;
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index d98c52aa91a..c698db2e8f5 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -50,6 +50,8 @@ struct RigidBodyWorld;
struct HookModifierData;
struct ModifierData;
+#include "DNA_object_enums.h"
+
void BKE_object_workob_clear(struct Object *workob);
void BKE_object_workob_calc_parent(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct Object *workob);
@@ -70,18 +72,18 @@ void BKE_object_free_caches(struct Object *object);
void BKE_object_modifier_hook_reset(struct Object *ob, struct HookModifierData *hmd);
-bool BKE_object_support_modifier_type_check(struct Object *ob, int modifier_type);
+bool BKE_object_support_modifier_type_check(const struct Object *ob, int modifier_type);
void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_src);
-void BKE_object_free_modifiers(struct Object *ob);
+void BKE_object_free_modifiers(struct Object *ob, const int flag);
void BKE_object_make_proxy(struct Object *ob, struct Object *target, struct Object *gob);
void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target);
-bool BKE_object_exists_check(struct Object *obtest);
-bool BKE_object_is_in_editmode(struct Object *ob);
-bool BKE_object_is_in_editmode_vgroup(struct Object *ob);
-bool BKE_object_is_in_wpaint_select_vert(struct Object *ob);
+bool BKE_object_exists_check(const struct Object *obtest);
+bool BKE_object_is_in_editmode(const struct Object *ob);
+bool BKE_object_is_in_editmode_vgroup(const struct Object *ob);
+bool BKE_object_is_in_wpaint_select_vert(const struct Object *ob);
typedef enum eObjectVisibilityCheck {
OB_VISIBILITY_CHECK_FOR_VIEWPORT,
@@ -121,8 +123,8 @@ void BKE_object_copy_data(struct Main *bmain, struct Object *ob_dst, const struc
struct Object *BKE_object_copy(struct Main *bmain, const struct Object *ob);
void BKE_object_make_local(struct Main *bmain, struct Object *ob, const bool lib_local);
void BKE_object_make_local_ex(struct Main *bmain, struct Object *ob, const bool lib_local, const bool clear_proxy);
-bool BKE_object_is_libdata(struct Object *ob);
-bool BKE_object_obdata_is_libdata(struct Object *ob);
+bool BKE_object_is_libdata(const struct Object *ob);
+bool BKE_object_obdata_is_libdata(const struct Object *ob);
void BKE_object_obdata_size_init(struct Object *ob, const float scale);
@@ -134,16 +136,23 @@ void BKE_object_to_mat4(struct Object *ob, float mat[4][4]);
void BKE_object_apply_mat4(struct Object *ob, float mat[4][4], const bool use_compat, const bool use_parent);
void BKE_object_matrix_local_get(struct Object *ob, float mat[4][4]);
-bool BKE_object_pose_context_check(struct Object *ob);
+bool BKE_object_pose_context_check(const struct Object *ob);
struct Object *BKE_object_pose_armature_get(struct Object *ob);
+struct Object *BKE_object_pose_armature_get_visible(struct Object *ob, struct ViewLayer *view_layer);
-void BKE_object_get_parent_matrix(struct Scene *scene, struct Object *ob,
- struct Object *par, float parentmat[4][4]);
-void BKE_object_where_is_calc(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
-void BKE_object_where_is_calc_ex(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct RigidBodyWorld *rbw, struct Object *ob, float r_originmat[3][3]);
-void BKE_object_where_is_calc_time(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, float ctime);
-void BKE_object_where_is_calc_time_ex(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, float ctime,
- struct RigidBodyWorld *rbw, float r_originmat[3][3]);
+void BKE_object_get_parent_matrix(
+ struct Scene *scene, struct Object *ob,
+ struct Object *par, float parentmat[4][4]);
+void BKE_object_where_is_calc(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
+void BKE_object_where_is_calc_ex(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct RigidBodyWorld *rbw,
+ struct Object *ob, float r_originmat[3][3]);
+void BKE_object_where_is_calc_time(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, float ctime);
+void BKE_object_where_is_calc_time_ex(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, float ctime,
+ struct RigidBodyWorld *rbw, float r_originmat[3][3]);
void BKE_object_where_is_calc_mat4(struct Scene *scene, struct Object *ob, float obmat[4][4]);
/* possibly belong in own moduke? */
@@ -159,14 +168,17 @@ void BKE_object_dimensions_set(struct Object *ob, const float value[3]);
void BKE_object_empty_draw_type_set(struct Object *ob, const int value);
void BKE_object_boundbox_flag(struct Object *ob, int flag, const bool set);
void BKE_object_minmax(struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden);
-bool BKE_object_minmax_dupli(struct Scene *scene, struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden);
+bool BKE_object_minmax_dupli(
+ struct Scene *scene, struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden);
/* sometimes min-max isn't enough, we need to loop over each point */
-void BKE_object_foreach_display_point(struct Object *ob, float obmat[4][4],
- void (*func_cb)(const float[3], void *), void *user_data);
-void BKE_scene_foreach_display_point(struct Scene *scene,
- struct ViewLayer *view_layer,
- void (*func_cb)(const float[3], void *), void *user_data);
+void BKE_object_foreach_display_point(
+ struct Object *ob, float obmat[4][4],
+ void (*func_cb)(const float[3], void *), void *user_data);
+void BKE_scene_foreach_display_point(
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ void (*func_cb)(const float[3], void *), void *user_data);
bool BKE_object_parent_loop_check(const struct Object *parent, const struct Object *ob);
@@ -182,48 +194,61 @@ typedef struct ObjectTfmProtectedChannels {
float rotAngle, drotAngle;
} ObjectTfmProtectedChannels;
-void BKE_object_tfm_protected_backup(const struct Object *ob,
- ObjectTfmProtectedChannels *obtfm);
+void BKE_object_tfm_protected_backup(
+ const struct Object *ob,
+ ObjectTfmProtectedChannels *obtfm);
-void BKE_object_tfm_protected_restore(struct Object *ob,
- const ObjectTfmProtectedChannels *obtfm,
- const short protectflag);
+void BKE_object_tfm_protected_restore(
+ struct Object *ob,
+ const ObjectTfmProtectedChannels *obtfm,
+ const short protectflag);
/* Dependency graph evaluation callbacks. */
-void BKE_object_eval_local_transform(const struct EvaluationContext *eval_ctx,
- struct Object *ob);
-void BKE_object_eval_parent(const struct EvaluationContext *eval_ctx,
- struct Scene *scene,
- struct Object *ob);
-void BKE_object_eval_constraints(const struct EvaluationContext *eval_ctx,
- struct Scene *scene,
- struct Object *ob);
+void BKE_object_eval_local_transform(
+ const struct EvaluationContext *eval_ctx,
+ struct Object *ob);
+void BKE_object_eval_parent(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob);
+void BKE_object_eval_constraints(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob);
void BKE_object_eval_done(const struct EvaluationContext *eval_ctx, struct Object *ob);
-bool BKE_object_eval_proxy_copy(const struct EvaluationContext *eval_ct,
- struct Object *object);
-void BKE_object_eval_uber_transform(const struct EvaluationContext *eval_ctx,
- struct Object *ob);
-void BKE_object_eval_uber_data(const struct EvaluationContext *eval_ctx,
- struct Scene *scene,
- struct Object *ob);
+bool BKE_object_eval_proxy_copy(
+ const struct EvaluationContext *eval_ctx,
+ struct Object *object);
+void BKE_object_eval_uber_transform(
+ const struct EvaluationContext *eval_ctx,
+ struct Object *ob);
+void BKE_object_eval_uber_data(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob);
-void BKE_object_eval_cloth(const struct EvaluationContext *eval_ctx,
- struct Scene *scene,
- struct Object *object);
+void BKE_object_eval_cloth(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *object);
-void BKE_object_eval_transform_all(const struct EvaluationContext *eval_ctx,
- struct Scene *scene,
- struct Object *object);
+void BKE_object_eval_transform_all(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *object);
-void BKE_object_eval_update_shading(const struct EvaluationContext *eval_ctx,
- struct Object *object);
-void BKE_object_data_select_update(const struct EvaluationContext *eval_ctx,
- struct ID *object_data);
+void BKE_object_eval_update_shading(
+ const struct EvaluationContext *eval_ctx,
+ struct Object *object);
+void BKE_object_data_select_update(
+ const struct EvaluationContext *eval_ctx,
+ struct ID *object_data);
-void BKE_object_eval_flush_base_flags(const struct EvaluationContext *eval_ctx,
- struct Object *object, struct Base *base,
- const bool is_from_set);
+void BKE_object_eval_flush_base_flags(
+ const struct EvaluationContext *eval_ctx,
+ struct Object *object, int base_index,
+ const bool is_from_set);
void BKE_object_handle_data_update(
const struct EvaluationContext *eval_ctx,
@@ -237,7 +262,6 @@ void BKE_object_handle_update_ex(
struct Scene *scene, struct Object *ob,
struct RigidBodyWorld *rbw,
const bool do_proxy_update);
-
void BKE_object_sculpt_modifiers_changed(struct Object *ob);
int BKE_object_obdata_texspace_get(struct Object *ob, short **r_texflag, float **r_loc, float **r_size, float **r_rot);
@@ -250,7 +274,7 @@ bool BKE_object_shapekey_free(struct Main *bmain, struct Object *ob);
bool BKE_object_flag_test_recursive(const struct Object *ob, short flag);
-bool BKE_object_is_child_recursive(struct Object *ob_parent, struct Object *ob_child);
+bool BKE_object_is_child_recursive(const struct Object *ob_parent, const struct Object *ob_child);
bool BKE_object_is_animated(struct Scene *scene, struct Object *ob);
/* return ModifierMode flag */
@@ -280,7 +304,8 @@ typedef enum eObjectSet {
OB_SET_ALL /* All Objects */
} eObjectSet;
-struct LinkNode *BKE_object_relational_superset(struct ViewLayer *view_layer, eObjectSet objectSet, eObRelationTypes includeFilter);
+struct LinkNode *BKE_object_relational_superset(
+ struct ViewLayer *view_layer, eObjectSet objectSet, eObRelationTypes includeFilter);
struct LinkNode *BKE_object_groups(struct Object *ob);
void BKE_object_groups_clear(struct Object *object);
@@ -288,8 +313,9 @@ struct KDTree *BKE_object_as_kdtree(struct Object *ob, int *r_tot);
bool BKE_object_modifier_use_time(struct Object *ob, struct ModifierData *md);
-bool BKE_object_modifier_update_subframe(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
- bool update_mesh, int parent_recursion, float frame, int type);
+bool BKE_object_modifier_update_subframe(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
+ bool update_mesh, int parent_recursion, float frame, int type);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_object_deform.h b/source/blender/blenkernel/BKE_object_deform.h
index 19a2220006a..ab54330cf53 100644
--- a/source/blender/blenkernel/BKE_object_deform.h
+++ b/source/blender/blenkernel/BKE_object_deform.h
@@ -54,7 +54,8 @@ void BKE_object_defgroup_remove(struct Object *ob, struct bDeformGroup *defgroup
void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked);
void BKE_object_defgroup_remove_all(struct Object *ob);
-
+int *BKE_object_defgroup_index_map_create(struct Object *ob_src, struct Object *ob_dst, int *r_map_len);
+void BKE_object_defgroup_index_map_apply(struct MDeformVert *dvert, int dvert_len, const int *map, int map_len);
/* Select helpers */
enum eVGroupSelect;
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index b952859e508..fa67c07395d 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -62,6 +62,8 @@ struct EvaluationContext;
enum eOverlayFlags;
+#include "DNA_object_enums.h"
+
extern const char PAINT_CURSOR_SCULPT[3];
extern const char PAINT_CURSOR_VERTEX_PAINT[3];
extern const char PAINT_CURSOR_WEIGHT_PAINT[3];
@@ -124,7 +126,7 @@ void BKE_paint_copy(struct Paint *src, struct Paint *tar, const int flag);
void BKE_paint_cavity_curve_preset(struct Paint *p, int preset);
-short BKE_paint_object_mode_from_paint_mode(ePaintMode mode);
+eObjectMode BKE_paint_object_mode_from_paint_mode(ePaintMode mode);
struct Paint *BKE_paint_get_active_from_paintmode(struct Scene *sce, ePaintMode mode);
struct Paint *BKE_paint_get_active(struct Scene *sce, struct ViewLayer *view_layer);
struct Paint *BKE_paint_get_active_from_context(const struct bContext *C);
@@ -214,7 +216,6 @@ typedef struct SculptSession {
/* Layer brush persistence between strokes */
float (*layer_co)[3]; /* Copy of the mesh vertices' locations */
- struct SculptStroke *stroke;
struct StrokeCache *cache;
union {
@@ -256,6 +257,7 @@ void BKE_sculpt_update_mesh_elements(
struct MultiresModifierData *BKE_sculpt_multires_active(struct Scene *scene, struct Object *ob);
int BKE_sculpt_mask_layers_ensure(struct Object *ob,
struct MultiresModifierData *mmd);
+void BKE_sculpt_toolsettings_data_ensure(struct Scene *scene);
enum {
SCULPT_MASK_LAYER_CALC_VERT = (1 << 0),
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index a374a20f82a..dd563617674 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -49,6 +49,7 @@ struct ParticleSettings;
struct Main;
struct Object;
struct Scene;
+struct Depsgraph;
struct DerivedMesh;
struct ModifierData;
struct MTFace;
@@ -115,6 +116,7 @@ typedef struct ParticleTexture {
float damp, gravity, field; /* used in physics */
float length, clump, kink_freq, kink_amp, effector; /* used in path caching */
float rough1, rough2, roughe; /* used in path caching */
+ float twist; /* used in path caching */
} ParticleTexture;
typedef struct ParticleSeam {
@@ -146,7 +148,7 @@ typedef struct ParticleThreadContext {
float *jit, *jitoff, *weight;
float maxweight;
- int *index, *skip, jitlevel;
+ int *index, jitlevel;
int cfrom, distr;
@@ -162,9 +164,11 @@ typedef struct ParticleThreadContext {
float *vg_length, *vg_clump, *vg_kink;
float *vg_rough1, *vg_rough2, *vg_roughe;
float *vg_effector;
+ float *vg_twist;
struct CurveMapping *clumpcurve;
struct CurveMapping *roughcurve;
+ struct CurveMapping *twistcurve;
} ParticleThreadContext;
typedef struct ParticleTask {
@@ -286,8 +290,8 @@ BLI_INLINE void psys_frand_vec(ParticleSystem *psys, unsigned int seed, float ve
int count_particles(struct ParticleSystem *psys);
int count_particles_mod(struct ParticleSystem *psys, int totgr, int cur);
-int psys_get_child_number(struct Scene *scene, struct ParticleSystem *psys);
-int psys_get_tot_child(struct Scene *scene, struct ParticleSystem *psys);
+int psys_get_child_number(struct Scene *scene, struct ParticleSystem *psys, const bool use_render_params);
+int psys_get_tot_child(struct Scene *scene, struct ParticleSystem *psys, const bool use_render_params);
struct ParticleSystem *psys_get_current(struct Object *ob);
/* for rna */
@@ -298,7 +302,7 @@ void psys_set_current_num(Object *ob, int index);
struct LatticeDeformData *psys_create_lattice_deform_data(struct ParticleSimulationData *sim);
-bool psys_in_edit_mode(struct ViewLayer *view_layer, struct ParticleSystem *psys);
+bool psys_in_edit_mode(struct Depsgraph *depsgraph, struct ParticleSystem *psys);
bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys, const bool use_render_params);
bool psys_check_edited(struct ParticleSystem *psys);
@@ -310,8 +314,6 @@ void BKE_particlesettings_free(struct ParticleSettings *part);
void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit);
void psys_free(struct Object *ob, struct ParticleSystem *psys);
-void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset);
-void psys_render_restore(struct Object *ob, struct ParticleSystem *psys);
bool psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params);
void psys_interpolate_uvs(const struct MTFace *tface, int quad, const float w[4], float uvco[2]);
@@ -352,6 +354,7 @@ int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct Pa
/* child paths */
void BKE_particlesettings_clump_curve_init(struct ParticleSettings *part);
void BKE_particlesettings_rough_curve_init(struct ParticleSettings *part);
+void BKE_particlesettings_twist_curve_init(struct ParticleSettings *part);
void psys_apply_child_modifiers(struct ParticleThreadContext *ctx, struct ListBase *modifiers,
struct ChildParticle *cpa, struct ParticleTexture *ptex, const float orco[3], const float ornor[3], float hairmat[4][4],
struct ParticleCacheKey *keys, struct ParticleCacheKey *parent_keys, const float parent_orco[3]);
@@ -438,34 +441,7 @@ int psys_particle_dm_face_lookup(struct DerivedMesh *dm_final, struct DerivedMes
void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, float dtime, float cfra);
-float psys_get_current_display_percentage(struct ParticleSystem *psys);
-
-typedef struct ParticleRenderElem {
- int curchild, totchild, reduce;
- float lambda, t, scalemin, scalemax;
-} ParticleRenderElem;
-
-typedef struct ParticleRenderData {
- ChildParticle *child;
- ParticleCacheKey **pathcache;
- ParticleCacheKey **childcache;
- ListBase pathcachebufs, childcachebufs;
- int totchild, totcached, totchildcache;
- struct DerivedMesh *dm;
- int totdmvert, totdmedge, totdmface;
-
- float mat[4][4];
- float viewmat[4][4], winmat[4][4];
- int winx, winy;
-
- int do_simplify;
- int timeoffset;
- ParticleRenderElem *elems;
-
- /* ORIGINDEX */
- const int *index_mf_to_mpoly;
- const int *index_mp_to_orig;
-} ParticleRenderData;
+float psys_get_current_display_percentage(struct ParticleSystem *psys, const bool use_render_params);
/* psys_reset */
#define PSYS_RESET_ALL 1
@@ -481,11 +457,6 @@ typedef struct ParticleRenderData {
struct EvaluationContext;
-void BKE_particle_system_settings_eval(const struct EvaluationContext *eval_ctx,
- struct ParticleSystem *psys);
-void BKE_particle_system_settings_recalc_clear(struct EvaluationContext *UNUSED(eval_ctx),
- struct ParticleSettings *particle_settings);
-
void BKE_particle_system_eval_init(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index 9a5a9e9e56a..89f1aa5eadd 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -34,7 +34,7 @@
#include "DNA_ID.h"
#include "DNA_dynamicpaint_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_boid_types.h"
#include <stdio.h> /* for FILE */
@@ -141,7 +141,7 @@ typedef struct PTCacheID {
unsigned int default_step;
unsigned int max_step;
- /* flags defined in DNA_object_force.h */
+ /* flags defined in DNA_object_force_types.h */
unsigned int data_types, info_types;
/* copies point data to cache data */
@@ -230,7 +230,6 @@ typedef struct PTCacheEditPoint {
} PTCacheEditPoint;
typedef struct PTCacheUndo {
- struct PTCacheUndo *next, *prev;
struct PTCacheEditPoint *points;
/* particles stuff */
@@ -243,12 +242,11 @@ typedef struct PTCacheUndo {
struct ListBase mem_cache;
int totpoint;
- char name[64];
+
+ size_t undo_size;
} PTCacheUndo;
typedef struct PTCacheEdit {
- ListBase undo;
- struct PTCacheUndo *curundo;
PTCacheEditPoint *points;
struct PTCacheID pid;
@@ -279,6 +277,7 @@ void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeMo
void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, struct Object *ob, struct DynamicPaintSurface *surface);
void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, struct Object *ob, struct RigidBodyWorld *rbw);
+PTCacheID BKE_ptcache_id_find(struct Object *ob, struct Scene *scene, struct PointCache *cache);
void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob, struct Scene *scene, int duplis);
/***************** Global funcs ****************************/
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index bb435df136d..4a97cb763dc 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -111,6 +111,9 @@ void BKE_scene_object_base_flag_sync_from_object(struct Base *base);
void BKE_scene_set_background(struct Main *bmain, struct Scene *sce);
struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name);
+struct ToolSettings *BKE_toolsettings_copy(struct ToolSettings *toolsettings, const int flag);
+void BKE_toolsettings_free(struct ToolSettings *toolsettings);
+
void BKE_scene_copy_data(struct Main *bmain, struct Scene *sce_dst, const struct Scene *sce_src, const int flag);
struct Scene *BKE_scene_copy(struct Main *bmain, struct Scene *sce, int type);
void BKE_scene_groups_relink(struct Scene *sce);
@@ -136,17 +139,11 @@ void BKE_scene_frame_set(struct Scene *scene, double cfra);
/* ** Scene evaluation ** */
-void BKE_scene_graph_update_tagged(struct EvaluationContext *eval_ctx,
- struct Depsgraph *depsgraph,
- struct Main *bmain,
- struct Scene *scene,
- struct ViewLayer *view_layer);
-
-void BKE_scene_graph_update_for_newframe(struct EvaluationContext *eval_ctx,
- struct Depsgraph *depsgraph,
- struct Main *bmain,
- struct Scene *scene,
- struct ViewLayer *view_layer);
+void BKE_scene_graph_update_tagged(struct Depsgraph *depsgraph,
+ struct Main *bmain);
+
+void BKE_scene_graph_update_for_newframe(struct Depsgraph *depsgraph,
+ struct Main *bmain);
struct SceneRenderView *BKE_scene_add_render_view(struct Scene *sce, const char *name);
bool BKE_scene_remove_render_view(struct Scene *scene, struct SceneRenderView *srv);
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 6669f3103da..fd6b3d20fb7 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -194,6 +194,7 @@ typedef struct PanelType {
char translation_context[BKE_ST_MAXNAME];
char context[BKE_ST_MAXNAME]; /* for buttons window */
char category[BKE_ST_MAXNAME]; /* for category tabs */
+ char owner_id[BKE_ST_MAXNAME]; /* for work-spaces to selectively show. */
int space_type;
int region_type;
@@ -264,6 +265,7 @@ typedef struct MenuType {
char idname[BKE_ST_MAXNAME]; /* unique name */
char label[BKE_ST_MAXNAME]; /* for button text */
char translation_context[BKE_ST_MAXNAME];
+ char owner_id[BKE_ST_MAXNAME]; /* optional, see: #wmOwnerID */
const char *description;
/* verify if the menu should draw or not */
@@ -325,7 +327,6 @@ void BKE_screen_view3d_scene_sync(struct bScreen *sc, struct Scene *scene);
void BKE_screen_transform_orientation_remove(
const struct bScreen *screen, const struct WorkSpace *workspace,
const struct TransformOrientation *orientation) ATTR_NONNULL();
-void BKE_screen_gpu_fx_validate(struct GPUFXSettings *fx_settings);
bool BKE_screen_is_fullscreen_area(const struct bScreen *screen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool BKE_screen_is_used(const struct bScreen *screen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 2264167eca1..21f3f344e64 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -40,6 +40,7 @@ struct GPUFX;
struct ImBuf;
struct Main;
struct Mask;
+struct RenderEngineType;
struct Scene;
struct Sequence;
struct SequenceModifierData;
@@ -405,6 +406,8 @@ struct Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine);
void BKE_sequence_alpha_mode_from_extension(struct Sequence *seq);
void BKE_sequence_init_colorspace(struct Sequence *seq);
+float BKE_sequence_get_fps(struct Scene *scene, struct Sequence *seq);
+
/* RNA enums, just to be more readable */
enum {
SEQ_SIDE_NONE = 0,
@@ -433,10 +436,11 @@ enum {
typedef struct ImBuf *(*SequencerDrawView)(
const struct EvaluationContext *eval_ctx, struct Scene *scene,
- struct ViewLayer *view_layer, struct Object *camera, int width, int height,
+ struct ViewLayer *view_layer, struct RenderEngineType *engine_type,
+ struct Object *camera, int width, int height,
unsigned int flag, unsigned int draw_flags, int drawtype, int alpha_mode,
int samples, const char *viewname,
- struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
+ struct GPUOffScreen *ofs, char err_out[256]);
extern SequencerDrawView sequencer_view3d_cb;
/* copy/paste */
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index 14d3318e059..98db06752c8 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -40,6 +40,7 @@ extern "C" {
struct Main;
struct Text;
struct TextLine;
+struct TextUndoBuf;
void BKE_text_free_lines (struct Text *text);
void BKE_text_free (struct Text *text);
@@ -55,8 +56,8 @@ struct Text *BKE_text_load (struct Main *bmain, const char *file, const char
void BKE_text_copy_data(struct Main *bmain, struct Text *ta_dst, const struct Text *ta_src, const int flag);
struct Text *BKE_text_copy (struct Main *bmain, const struct Text *ta);
void BKE_text_make_local (struct Main *bmain, struct Text *text, const bool lib_local);
-void BKE_text_clear (struct Text *text);
-void BKE_text_write (struct Text *text, const char *str);
+void BKE_text_clear (struct Text *text, struct TextUndoBuf *utxt);
+void BKE_text_write (struct Text *text, struct TextUndoBuf *utxt, const char *str);
int BKE_text_file_modified_check(struct Text *text);
void BKE_text_file_modified_ignore(struct Text *text);
@@ -83,29 +84,29 @@ void txt_move_eol (struct Text *text, const bool sel);
void txt_move_toline (struct Text *text, unsigned int line, const bool sel);
void txt_move_to (struct Text *text, unsigned int line, unsigned int ch, const bool sel);
void txt_pop_sel (struct Text *text);
-void txt_delete_char (struct Text *text);
-void txt_delete_word (struct Text *text);
-void txt_delete_selected (struct Text *text);
+void txt_delete_char (struct Text *text, struct TextUndoBuf *utxt);
+void txt_delete_word (struct Text *text, struct TextUndoBuf *utxt);
+void txt_delete_selected (struct Text *text, struct TextUndoBuf *utxt);
void txt_sel_all (struct Text *text);
void txt_sel_clear (struct Text *text);
void txt_sel_line (struct Text *text);
char *txt_sel_to_buf (struct Text *text);
-void txt_insert_buf (struct Text *text, const char *in_buffer);
-void txt_undo_add_op (struct Text *text, int op);
-void txt_do_undo (struct Text *text);
-void txt_do_redo (struct Text *text);
-void txt_split_curline (struct Text *text);
-void txt_backspace_char (struct Text *text);
-void txt_backspace_word (struct Text *text);
-bool txt_add_char (struct Text *text, unsigned int add);
-bool txt_add_raw_char (struct Text *text, unsigned int add);
-bool txt_replace_char (struct Text *text, unsigned int add);
-void txt_unindent (struct Text *text);
-void txt_comment (struct Text *text);
-void txt_indent (struct Text *text);
-void txt_uncomment (struct Text *text);
-void txt_move_lines (struct Text *text, const int direction);
-void txt_duplicate_line (struct Text *text);
+void txt_insert_buf (struct Text *text, struct TextUndoBuf *utxt, const char *in_buffer);
+void txt_undo_add_op (struct Text *text, struct TextUndoBuf *utxt, int op);
+void txt_do_undo (struct Text *text, struct TextUndoBuf *utxt);
+void txt_do_redo (struct Text *text, struct TextUndoBuf *utxt);
+void txt_split_curline (struct Text *text, struct TextUndoBuf *utxt);
+void txt_backspace_char (struct Text *text, struct TextUndoBuf *utxt);
+void txt_backspace_word (struct Text *text, struct TextUndoBuf *utxt);
+bool txt_add_char (struct Text *text, struct TextUndoBuf *utxt, unsigned int add);
+bool txt_add_raw_char (struct Text *text, struct TextUndoBuf *utxt, unsigned int add);
+bool txt_replace_char (struct Text *text, struct TextUndoBuf *utxt, unsigned int add);
+void txt_unindent (struct Text *text, struct TextUndoBuf *utxt);
+void txt_comment (struct Text *text, struct TextUndoBuf *utxt);
+void txt_indent (struct Text *text, struct TextUndoBuf *utxt);
+void txt_uncomment (struct Text *text, struct TextUndoBuf *utxt);
+void txt_move_lines (struct Text *text, struct TextUndoBuf *utxt, const int direction);
+void txt_duplicate_line (struct Text *text, struct TextUndoBuf *utxt);
int txt_setcurr_tab_spaces(struct Text *text, int space);
bool txt_cursor_is_line_start(struct Text *text);
bool txt_cursor_is_line_end(struct Text *text);
@@ -135,46 +136,10 @@ enum {
TXT_MOVE_LINE_DOWN = 1
};
-
-/* Undo opcodes */
-
-/* Complex editing */
-/* 1 - opcode is followed by 1 byte for ascii character and opcode (repeat)) */
-/* 2 - opcode is followed by 2 bytes for utf-8 character and opcode (repeat)) */
-/* 3 - opcode is followed by 3 bytes for utf-8 character and opcode (repeat)) */
-/* 4 - opcode is followed by 4 bytes for unicode character and opcode (repeat)) */
-#define UNDO_INSERT_1 013
-#define UNDO_INSERT_2 014
-#define UNDO_INSERT_3 015
-#define UNDO_INSERT_4 016
-
-#define UNDO_BS_1 017
-#define UNDO_BS_2 020
-#define UNDO_BS_3 021
-#define UNDO_BS_4 022
-
-#define UNDO_DEL_1 023
-#define UNDO_DEL_2 024
-#define UNDO_DEL_3 025
-#define UNDO_DEL_4 026
-
-/* Text block (opcode is followed
- * by 4 character length ID + the text
- * block itself + the 4 character length
- * ID (repeat) and opcode (repeat)) */
-#define UNDO_DBLOCK 027 /* Delete block */
-#define UNDO_IBLOCK 030 /* Insert block */
-
-/* Misc */
-#define UNDO_INDENT 032
-#define UNDO_UNINDENT 033
-#define UNDO_COMMENT 034
-#define UNDO_UNCOMMENT 035
-
-#define UNDO_MOVE_LINES_UP 036
-#define UNDO_MOVE_LINES_DOWN 037
-
-#define UNDO_DUPLICATE 040
+typedef struct TextUndoBuf {
+ char *buf;
+ int pos, len;
+} TextUndoBuf;
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h
new file mode 100644
index 00000000000..53ea8ddefe8
--- /dev/null
+++ b/source/blender/blenkernel/BKE_undo_system.h
@@ -0,0 +1,197 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BKE_UNDO_SYSTEM_H__
+#define __BKE_UNDO_SYSTEM_H__
+
+/** \file BKE_undo_system.h
+ * \ingroup bke
+ */
+
+struct Main;
+struct UndoStep;
+struct bContext;
+
+/* ID's */
+struct Mesh;
+struct Object;
+struct Scene;
+struct Text;
+
+#include "DNA_ID.h"
+#include "DNA_listBase.h"
+
+typedef struct UndoRefID { struct ID *ptr; char name[MAX_ID_NAME]; } UndoRefID;
+/* UndoRefID_Mesh & friends. */
+#define UNDO_REF_ID_TYPE(ptr_ty) \
+ typedef struct UndoRefID_##ptr_ty { struct ptr_ty *ptr; char name[MAX_ID_NAME]; } UndoRefID_##ptr_ty
+UNDO_REF_ID_TYPE(Mesh);
+UNDO_REF_ID_TYPE(Object);
+UNDO_REF_ID_TYPE(Scene);
+UNDO_REF_ID_TYPE(Text);
+
+typedef struct UndoStack {
+ ListBase steps;
+ struct UndoStep *step_active;
+
+ /**
+ * Some undo systems require begin/end, see: #UndoType.step_encode_init
+ *
+ * \note This is not included in the 'steps' list.
+ * That is done once end is called.
+ */
+ struct UndoStep *step_init;
+} UndoStack;
+
+
+typedef struct UndoStep {
+ struct UndoStep *next, *prev;
+ char name[64];
+ const struct UndoType *type;
+ /** Size in bytes of all data in step (not including the step). */
+ size_t data_size;
+ /** Users should never see this step (only use for internal consistency). */
+ bool skip;
+ /* Over alloc 'type->struct_size'. */
+} UndoStep;
+
+typedef enum eUndoTypeMode {
+ /**
+ * Each undo step stores a version of the state.
+ * This means we can simply load in a previous state at any time.
+ */
+ BKE_UNDOTYPE_MODE_STORE = 1,
+ /**
+ * Each undo step is a series of edits.
+ * This means to change states we need to apply each edit.
+ * It also means the 'step_decode' callback needs to detect the difference between undo and redo.
+ * (Currently used for text edit and image & sculpt painting).
+ */
+ BKE_UNDOTYPE_MODE_ACCUMULATE = 2,
+} eUndoTypeMode;
+
+typedef void (*UndoTypeForEachIDRefFn)(void *user_data, struct UndoRefID *id_ref);
+
+typedef struct UndoType {
+ struct UndoType *next, *prev;
+ /** Only for debugging. */
+ const char *name;
+
+ /**
+ * When NULL, we don't consider this undo type for context checks.
+ * Operators must explicitly set the undo type and handle adding the undo step.
+ * This is needed when tools operate on data which isn't the primary mode (eg, paint-curve in sculpt mode).
+ */
+ bool (*poll)(struct bContext *C);
+
+ /**
+ * None of these callbacks manage list add/removal.
+ *
+ * Note that 'step_encode_init' is optional,
+ * some undo types need to perform operatons before undo push finishes.
+ */
+ void (*step_encode_init)(struct bContext *C, UndoStep *us);
+
+ bool (*step_encode)(struct bContext *C, UndoStep *us);
+ void (*step_decode)(struct bContext *C, UndoStep *us, int dir);
+
+ /**
+ * \note When freeing all steps,
+ * free from the last since #MemFileUndoType will merge with the next undo type in the list. */
+ void (*step_free)(UndoStep *us);
+
+ void (*step_foreach_ID_ref)(UndoStep *us, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data);
+
+ eUndoTypeMode mode;
+ bool use_context;
+
+ int step_size;
+} UndoType;
+
+/* expose since we need to perform operations on spesific undo types (rarely). */
+extern const UndoType *BKE_UNDOSYS_TYPE_IMAGE;
+extern const UndoType *BKE_UNDOSYS_TYPE_MEMFILE;
+extern const UndoType *BKE_UNDOSYS_TYPE_PAINTCURVE;
+extern const UndoType *BKE_UNDOSYS_TYPE_PARTICLE;
+extern const UndoType *BKE_UNDOSYS_TYPE_SCULPT;
+extern const UndoType *BKE_UNDOSYS_TYPE_TEXT;
+
+UndoStack *BKE_undosys_stack_create(void);
+void BKE_undosys_stack_destroy(UndoStack *ustack);
+void BKE_undosys_stack_clear(UndoStack *ustack);
+bool BKE_undosys_stack_has_undo(UndoStack *ustack, const char *name);
+void BKE_undosys_stack_init_from_main(UndoStack *ustack, struct Main *bmain);
+UndoStep *BKE_undosys_stack_active_with_type(UndoStack *ustack, const UndoType *ut);
+UndoStep *BKE_undosys_stack_init_or_active_with_type(UndoStack *ustack, const UndoType *ut);
+void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size_t memory_limit);
+
+/* Only some UndoType's require init. */
+UndoStep *BKE_undosys_step_push_init_with_type(UndoStack *ustack, struct bContext *C, const char *name, const UndoType *ut);
+UndoStep *BKE_undosys_step_push_init(UndoStack *ustack, struct bContext *C, const char *name);
+
+bool BKE_undosys_step_push_with_type(UndoStack *ustack, struct bContext *C, const char *name, const UndoType *ut);
+bool BKE_undosys_step_push(UndoStack *ustack, struct bContext *C, const char *name);
+
+UndoStep *BKE_undosys_step_find_by_name_with_type(UndoStack *ustack, const char *name, const UndoType *ut);
+UndoStep *BKE_undosys_step_find_by_type(UndoStack *ustack, const UndoType *ut);
+UndoStep *BKE_undosys_step_find_by_name(UndoStack *ustack, const char *name);
+
+bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack, struct bContext *C, UndoStep *us, bool use_skip);
+bool BKE_undosys_step_undo_with_data(UndoStack *ustack, struct bContext *C, UndoStep *us);
+bool BKE_undosys_step_undo(UndoStack *ustack, struct bContext *C);
+
+bool BKE_undosys_step_redo_with_data_ex(UndoStack *ustack, struct bContext *C, UndoStep *us, bool use_skip);
+bool BKE_undosys_step_redo_with_data(UndoStack *ustack, struct bContext *C, UndoStep *us);
+bool BKE_undosys_step_redo(UndoStack *ustack, struct bContext *C);
+
+bool BKE_undosys_step_load_data(UndoStack *ustack, struct bContext *C, UndoStep *us);
+
+bool BKE_undosys_step_undo_compat_only(UndoStack *ustack, struct bContext *C, int step);
+void BKE_undosys_step_undo_from_index(UndoStack *ustack, struct bContext *C, int index);
+UndoStep *BKE_undosys_step_same_type_next(UndoStep *us);
+UndoStep *BKE_undosys_step_same_type_prev(UndoStep *us);
+
+/* Type System */
+UndoType *BKE_undosys_type_append(void (*undosys_fn)(UndoType *));
+void BKE_undosys_type_free_all(void);
+
+/* ID Accessor */
+#if 0 /* functionality is only used internally for now. */
+void BKE_undosys_foreach_ID_ref(UndoStack *ustack, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data);
+#endif
+
+/* Use when the undo step stores many arbitrary pointers. */
+struct UndoIDPtrMap;
+struct UndoIDPtrMap *BKE_undosys_ID_map_create(void);
+void BKE_undosys_ID_map_destroy(struct UndoIDPtrMap *map);
+void BKE_undosys_ID_map_add(struct UndoIDPtrMap *map, ID *id);
+struct ID *BKE_undosys_ID_map_lookup(const struct UndoIDPtrMap *map, const struct ID *id_src);
+
+void BKE_undosys_ID_map_add_with_prev(
+ struct UndoIDPtrMap *map, struct ID *id,
+ struct ID **id_prev);
+struct ID *BKE_undosys_ID_map_lookup_with_prev(
+ const struct UndoIDPtrMap *map, struct ID *id_src,
+ struct ID *id_prev_match[2]);
+
+void BKE_undosys_ID_map_foreach_ID_ref(
+ struct UndoIDPtrMap *map,
+ UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data);
+
+#endif /* __BKE_UNDO_SYSTEM_H__ */
diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h
index 9f989f7ae8f..32a9bcbec61 100644
--- a/source/blender/blenkernel/BKE_workspace.h
+++ b/source/blender/blenkernel/BKE_workspace.h
@@ -34,17 +34,6 @@ struct Scene;
struct TransformOrientation;
struct ViewLayer;
-/**
- * Plan is to store the object-mode per workspace, not per object anymore.
- * However, there's quite some work to be done for that, so for now, there is just a basic
- * implementation of an object <-> workspace object-mode syncing for testing, with some known
- * problems. Main problem being that the modes can get out of sync when changing object selection.
- * Would require a pile of temporary changes to always sync modes when changing selection. So just
- * leaving this here for some testing until object-mode is really a workspace level setting.
- */
-#define USE_WORKSPACE_MODE
-
-
/* -------------------------------------------------------------------- */
/* Create, delete, init */
@@ -106,15 +95,7 @@ void BKE_workspace_active_layout_set(struct WorkSpaceInstanceHook *h
struct bScreen *BKE_workspace_active_screen_get(const struct WorkSpaceInstanceHook *hook) GETTER_ATTRS;
void BKE_workspace_active_screen_set(
struct WorkSpaceInstanceHook *hook, struct WorkSpace *workspace, struct bScreen *screen) SETTER_ATTRS;
-#ifdef USE_WORKSPACE_MODE
-enum eObjectMode BKE_workspace_object_mode_get(
- const struct WorkSpace *workspace,
- const struct Scene *scene) GETTER_ATTRS;
-void BKE_workspace_object_mode_set(
- struct WorkSpace *workspace,
- struct Scene *scene,
- const enum eObjectMode mode) SETTER_ATTRS;
-#endif
+
struct Base *BKE_workspace_active_base_get(const struct WorkSpace *workspace, const struct Scene *scene);
struct ListBase *BKE_workspace_transform_orientations_get(struct WorkSpace *workspace) GETTER_ATTRS;
struct ViewLayer *BKE_workspace_view_layer_get(
@@ -144,11 +125,13 @@ bool BKE_workspace_use_scene_settings_get(const struct WorkSpace *workspace) GET
void BKE_workspace_use_scene_settings_set(struct WorkSpace *workspace, bool value) SETTER_ATTRS;
/* Update / evaluate */
-void BKE_workspace_update_tagged(struct EvaluationContext *eval_ctx,
- struct Main *bmain,
+void BKE_workspace_update_tagged(struct Main *bmain,
struct WorkSpace *workspace,
struct Scene *scene);
+bool BKE_workspace_owner_id_check(
+ const struct WorkSpace *workspace, const char *owner_id) ATTR_NONNULL();
+
#undef GETTER_ATTRS
#undef SETTER_ATTRS
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 03aa5e256b8..b6250ad86f4 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -49,6 +49,7 @@ set(INC
../../../intern/mikktspace
../../../intern/smoke/extern
../../../intern/atomic
+ ../../../intern/clog
../../../intern/libmv
../../../extern/curve_fit_nd
)
@@ -103,6 +104,7 @@ set(SRC
intern/displist.c
intern/dynamicpaint.c
intern/editderivedmesh.c
+ intern/editlattice.c
intern/editmesh.c
intern/editmesh_bvh.c
intern/editmesh_tangent.c
@@ -197,6 +199,7 @@ set(SRC
intern/tracking_solver.c
intern/tracking_stabilize.c
intern/tracking_util.c
+ intern/undo_system.c
intern/unit.c
intern/workspace.c
intern/world.c
@@ -242,6 +245,7 @@ set(SRC
BKE_deform.h
BKE_displist.h
BKE_dynamicpaint.h
+ BKE_editlattice.h
BKE_editmesh.h
BKE_editmesh_bvh.h
BKE_editmesh_tangent.h
@@ -314,6 +318,7 @@ set(SRC
BKE_text.h
BKE_texture.h
BKE_tracking.h
+ BKE_undo_system.h
BKE_unit.h
BKE_workspace.h
BKE_world.h
@@ -322,6 +327,7 @@ set(SRC
nla_private.h
tracking_private.h
+ particle_private.h
intern/CCGSubSurf.h
intern/CCGSubSurf_inline.h
intern/CCGSubSurf_intern.h
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index cfeca50a751..916e11dbd46 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -350,7 +350,7 @@ void DM_init(
dm->numPolyData = numPolys;
DM_init_funcs(dm);
-
+
dm->needsFree = 1;
dm->auto_bump_scale = -1.0f;
dm->dirty = 0;
@@ -410,7 +410,6 @@ int DM_release(DerivedMesh *dm)
if (dm->needsFree) {
bvhcache_free(&dm->bvhCache);
GPU_drawobject_free(dm);
-
CustomData_free(&dm->vertData, dm->numVertData);
CustomData_free(&dm->edgeData, dm->numEdgeData);
CustomData_free(&dm->faceData, dm->numTessFaceData);
@@ -1660,7 +1659,7 @@ static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape
cos = CustomData_get_layer_n(&dm->vertData, CD_SHAPEKEY, i);
kb->totelem = dm->numVertData;
- kb->data = kbcos = MEM_malloc_arrayN(kb->totelem, sizeof(float), "kbcos DerivedMesh.c");
+ kb->data = kbcos = MEM_malloc_arrayN(kb->totelem, 3 * sizeof(float), "kbcos DerivedMesh.c");
if (kb->uid == actshape_uid) {
MVert *mvert = dm->getVertArray(dm);
@@ -3483,17 +3482,25 @@ void DM_draw_attrib_vertex_uniforms(const DMVertexAttribs *attribs)
{
int i;
if (attribs->totorco) {
- glUniform1i(attribs->orco.gl_info_index, 0);
+ if (attribs->orco.gl_info_index != -1) {
+ glUniform1i(attribs->orco.gl_info_index, 0);
+ }
}
for (i = 0; i < attribs->tottface; i++) {
- glUniform1i(attribs->tface[i].gl_info_index, 0);
+ if (attribs->tface[i].gl_info_index != -1) {
+ glUniform1i(attribs->tface[i].gl_info_index, 0);
+ }
}
for (i = 0; i < attribs->totmcol; i++) {
- glUniform1i(attribs->mcol[i].gl_info_index, GPU_ATTR_INFO_SRGB);
+ if (attribs->mcol[i].gl_info_index != -1) {
+ glUniform1i(attribs->mcol[i].gl_info_index, GPU_ATTR_INFO_SRGB);
+ }
}
for (i = 0; i < attribs->tottang; i++) {
- glUniform1i(attribs->tang[i].gl_info_index, 0);
+ if (attribs->tang[i].gl_info_index != -1) {
+ glUniform1i(attribs->tang[i].gl_info_index, 0);
+ }
}
}
@@ -3719,7 +3726,7 @@ void DM_init_origspace(DerivedMesh *dm)
BKE_mesh_calc_poly_normal(mp, l, mv, p_nor);
axis_dominant_v3_to_m3(mat, p_nor);
- BLI_array_empty(vcos_2d);
+ BLI_array_clear(vcos_2d);
BLI_array_reserve(vcos_2d, mp->totloop);
for (j = 0; j < mp->totloop; j++, l++) {
mul_v3_m3v3(co, mat, mv[l->v].co);
diff --git a/source/blender/blenkernel/intern/addon.c b/source/blender/blenkernel/intern/addon.c
index 0ef12397fe7..689e0fb5ee6 100644
--- a/source/blender/blenkernel/intern/addon.c
+++ b/source/blender/blenkernel/intern/addon.c
@@ -27,13 +27,58 @@
#include <stddef.h>
#include <stdlib.h>
+#include "RNA_types.h"
+
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
+#include "BLI_string.h"
+#include "BLI_listbase.h"
#include "BKE_addon.h" /* own include */
+#include "BKE_idprop.h"
+
+#include "DNA_listBase.h"
+#include "DNA_userdef_types.h"
+
#include "MEM_guardedalloc.h"
+/* -------------------------------------------------------------------- */
+/** \name Add-on New/Free
+ * \{ */
+
+bAddon *BKE_addon_new(void)
+{
+ bAddon *addon = MEM_callocN(sizeof(bAddon), "bAddon");
+ return addon;
+}
+
+bAddon *BKE_addon_ensure(ListBase *addon_list, const char *module)
+{
+ bAddon *addon = BLI_findstring(addon_list, module, offsetof(bAddon, module));
+ if (addon == NULL) {
+ addon = BKE_addon_new();
+ BLI_strncpy(addon->module, module, sizeof(addon->module));
+ BLI_addtail(addon_list, addon);
+ }
+ return addon;
+}
+
+void BKE_addon_free(bAddon *addon)
+{
+ if (addon->prop) {
+ IDP_FreeProperty(addon->prop);
+ MEM_freeN(addon->prop);
+ }
+ MEM_freeN(addon);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add-on Preference API
+ * \{ */
+
static GHash *global_addonpreftype_hash = NULL;
@@ -81,3 +126,5 @@ void BKE_addon_pref_type_free(void)
BLI_ghash_free(global_addonpreftype_hash, NULL, MEM_freeN);
global_addonpreftype_hash = NULL;
}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 62df97c6afa..0b964145c7f 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -278,8 +278,6 @@ void animviz_get_object_motionpaths(Object *ob, ListBase *targets)
/* update scene for current frame */
static void motionpaths_calc_update_scene(Main *bmain,
- Scene *scene,
- ViewLayer *view_layer,
struct Depsgraph *depsgraph)
{
/* Do all updates
@@ -292,7 +290,7 @@ static void motionpaths_calc_update_scene(Main *bmain,
*
* TODO(sergey): Use evaluation context dedicated to motion paths.
*/
- BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
}
/* ........ */
@@ -369,7 +367,7 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
/* calculate path over requested range */
for (CFRA = sfra; CFRA <= efra; CFRA++) {
/* update relevant data for new frame */
- motionpaths_calc_update_scene(bmain, scene, eval_ctx->view_layer, eval_ctx->depsgraph);
+ motionpaths_calc_update_scene(bmain, eval_ctx->depsgraph);
/* perform baking for targets */
motionpaths_calc_bake_targets(scene, targets);
@@ -377,7 +375,7 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
/* reset original environment */
CFRA = cfra;
- motionpaths_calc_update_scene(bmain, scene, eval_ctx->view_layer, eval_ctx->depsgraph);
+ motionpaths_calc_update_scene(bmain, eval_ctx->depsgraph);
/* clear recalc flags from targets */
for (mpt = targets->first; mpt; mpt = mpt->next) {
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 58b476d3da5..ecdb180d2ed 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -77,6 +77,8 @@
#include "atomic_ops.h"
+#include "DEG_depsgraph.h"
+
/* ***************************************** */
/* AnimData API */
@@ -245,7 +247,7 @@ void BKE_animdata_free(ID *id, const bool do_id_user)
}
/* free nla data */
- free_nladata(&adt->nla_tracks);
+ BKE_nla_tracks_free(&adt->nla_tracks);
/* free drivers - stored as a list of F-Curves */
free_fcurves(&adt->drivers);
@@ -284,7 +286,7 @@ AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const bool do_action)
}
/* duplicate NLA data */
- copy_nladata(&dadt->nla_tracks, &adt->nla_tracks);
+ BKE_nla_tracks_copy(&dadt->nla_tracks, &adt->nla_tracks);
/* duplicate drivers (F-Curves) */
copy_fcurves(&dadt->drivers, &adt->drivers);
@@ -366,7 +368,7 @@ void BKE_animdata_merge_copy(ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes a
if (src->nla_tracks.first) {
ListBase tracks = {NULL, NULL};
- copy_nladata(&tracks, &src->nla_tracks);
+ BKE_nla_tracks_copy(&tracks, &src->nla_tracks);
BLI_movelisttolist(&dst->nla_tracks, &tracks);
}
@@ -820,7 +822,7 @@ char *BKE_animsys_fix_rna_path_rename(ID *owner_id, char *old_path, const char *
/* if no action, no need to proceed */
if (ELEM(NULL, owner_id, old_path)) {
- printf("early abort\n");
+ if (G.debug & G_DEBUG) printf("%s: early abort\n", __func__);
return old_path;
}
@@ -843,9 +845,9 @@ char *BKE_animsys_fix_rna_path_rename(ID *owner_id, char *old_path, const char *
}
/* fix given path */
- printf("%s | %s | oldpath = %p ", oldN, newN, old_path);
+ if (G.debug & G_DEBUG) printf("%s | %s | oldpath = %p ", oldN, newN, old_path);
result = rna_path_rename_fix(owner_id, prefix, oldN, newN, old_path, verify_paths);
- printf("result = %p\n", result);
+ if (G.debug & G_DEBUG) printf("path rename result = %p\n", result);
/* free the temp names */
MEM_freeN(oldN);
@@ -2879,18 +2881,34 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime)
/* ************** */
/* Evaluation API */
-#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-
void BKE_animsys_eval_animdata(const EvaluationContext *eval_ctx, ID *id)
{
AnimData *adt = BKE_animdata_from_id(id);
Scene *scene = NULL; /* XXX: this is only needed for flushing RNA updates,
* which should get handled as part of the dependency graph instead...
*/
- DEBUG_PRINT("%s on %s, time=%f\n\n", __func__, id->name, (double)eval_ctx->ctime);
+ DEG_debug_print_eval_time(__func__, id->name, id, eval_ctx->ctime);
BKE_animsys_evaluate_animdata(scene, id, adt, eval_ctx->ctime, ADT_RECALC_ANIM);
}
+/* TODO(sergey): This is slow lookup of driver from CoW datablock.
+ * Keep this for until we've got something smarter for depsgraph
+ * building.\
+ */
+static FCurve *find_driver_from_evaluated_id(ID *id, FCurve *fcu)
+{
+ /* We've got non-CoW datablock, can use f-curve as-is. */
+ if (id->orig_id == NULL) {
+ return fcu;
+ }
+ /*const*/ ID *id_orig = id->orig_id;
+ const AnimData *adt_orig = BKE_animdata_from_id(id_orig);
+ const AnimData *adt_cow = BKE_animdata_from_id(id);
+ const int fcu_index = BLI_findindex(&adt_orig->drivers, fcu);
+ BLI_assert(fcu_index != -1);
+ return BLI_findlink(&adt_cow->drivers, fcu_index);
+}
+
void BKE_animsys_eval_driver(const EvaluationContext *eval_ctx,
ID *id,
FCurve *fcu)
@@ -2900,11 +2918,10 @@ void BKE_animsys_eval_driver(const EvaluationContext *eval_ctx,
PointerRNA id_ptr;
bool ok = false;
- DEBUG_PRINT("%s on %s (%s[%d])\n",
- __func__,
- id->name,
- fcu->rna_path,
- fcu->array_index);
+ fcu = find_driver_from_evaluated_id(id, fcu);
+
+ DEG_debug_print_eval_subdata_index(
+ __func__, id->name, id, "fcu", fcu->rna_path, fcu, fcu->array_index);
RNA_id_pointer_create(id, &id_ptr);
@@ -2937,5 +2954,3 @@ void BKE_animsys_eval_driver(const EvaluationContext *eval_ctx,
}
}
}
-
-#undef DEBUG_PRINT
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 953fef067b4..0a8c97ff175 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -63,7 +63,6 @@
#include "BKE_DerivedMesh.h"
#include "BKE_deform.h"
#include "BKE_displist.h"
-#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index 1b8bf3feb10..29baaff32ba 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -47,10 +47,9 @@
#include "BIK_api.h"
-#include "BKE_global.h"
#include "BKE_main.h"
-#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
+#include "DEG_depsgraph.h"
/* ********************** SPLINE IK SOLVER ******************* */
@@ -559,14 +558,23 @@ void BKE_splineik_execute_tree(
/* *************** Depsgraph evaluation callbacks ************ */
+BLI_INLINE bPoseChannel *pose_pchan_get_indexed(Object *ob, int pchan_index)
+{
+ bPose *pose = ob->pose;
+ BLI_assert(pose != NULL);
+ BLI_assert(pchan_index >= 0);
+ BLI_assert(pchan_index < MEM_allocN_len(pose->chan_array) / sizeof(bPoseChannel *));
+ return pose->chan_array[pchan_index];
+}
+
void BKE_pose_eval_init(const struct EvaluationContext *UNUSED(eval_ctx),
Scene *UNUSED(scene),
- Object *ob,
- bPose *pose)
+ Object *ob)
{
- bPoseChannel *pchan;
+ bPose *pose = ob->pose;
+ BLI_assert(pose != NULL);
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
BLI_assert(ob->type == OB_ARMATURE);
@@ -577,27 +585,34 @@ void BKE_pose_eval_init(const struct EvaluationContext *UNUSED(eval_ctx),
/* imat is needed for solvers. */
invert_m4_m4(ob->imat, ob->obmat);
- /* 1. clear flags */
- for (pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
+ const int num_channels = BLI_listbase_count(&pose->chanbase);
+ pose->chan_array = MEM_malloc_arrayN(
+ num_channels, sizeof(bPoseChannel *), "pose->chan_array");
+
+ /* clear flags */
+ int pchan_index = 0;
+ for (bPoseChannel *pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
pchan->flag &= ~(POSE_DONE | POSE_CHAIN | POSE_IKTREE | POSE_IKSPLINE);
+ pose->chan_array[pchan_index++] = pchan;
}
}
void BKE_pose_eval_init_ik(const struct EvaluationContext *eval_ctx,
Scene *scene,
- Object *ob,
- bPose *UNUSED(pose))
+ Object *ob)
{
- float ctime = BKE_scene_frame_get(scene); /* not accurate... */
-
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
-
- /* 2a. construct the IK tree (standard IK) */
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
+ BLI_assert(ob->type == OB_ARMATURE);
+ const float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ bArmature *arm = (bArmature *)ob->data;
+ if (arm->flag & ARM_RESTPOS) {
+ return;
+ }
+ /* construct the IK tree (standard IK) */
BIK_initialize_tree(eval_ctx, scene, ob, ctime);
-
- /* 2b. construct the Spline IK trees
+ /* construct the Spline IK trees
* - this is not integrated as an IK plugin, since it should be able
- * to function in conjunction with standard IK
+ * to function in conjunction with standard IK
*/
BKE_pose_splineik_init_tree(scene, ob, ctime);
}
@@ -605,11 +620,13 @@ void BKE_pose_eval_init_ik(const struct EvaluationContext *eval_ctx,
void BKE_pose_eval_bone(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
- bPoseChannel *pchan)
+ int pchan_index)
{
- bArmature *arm = (bArmature *)ob->data;
- DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, pchan->name);
+ bPoseChannel *pchan = pose_pchan_get_indexed(ob, pchan_index);
+ DEG_debug_print_eval_subdata(
+ __func__, ob->id.name, ob, "pchan", pchan->name, pchan);
BLI_assert(ob->type == OB_ARMATURE);
+ bArmature *arm = (bArmature *)ob->data;
if (arm->edbo || (arm->flag & ARM_RESTPOS)) {
Bone *bone = pchan->bone;
if (bone) {
@@ -640,9 +657,11 @@ void BKE_pose_eval_bone(const struct EvaluationContext *eval_ctx,
void BKE_pose_constraints_evaluate(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
- bPoseChannel *pchan)
+ int pchan_index)
{
- DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, pchan->name);
+ bPoseChannel *pchan = pose_pchan_get_indexed(ob, pchan_index);
+ DEG_debug_print_eval_subdata(
+ __func__, ob->id.name, ob, "pchan", pchan->name, pchan);
bArmature *arm = (bArmature *)ob->data;
if (arm->flag & ARM_RESTPOS) {
return;
@@ -659,10 +678,12 @@ void BKE_pose_constraints_evaluate(const struct EvaluationContext *eval_ctx,
}
void BKE_pose_bone_done(const struct EvaluationContext *UNUSED(eval_ctx),
- bPoseChannel *pchan)
+ struct Object *ob,
+ int pchan_index)
{
+ bPoseChannel *pchan = pose_pchan_get_indexed(ob, pchan_index);
float imat[4][4];
- DEBUG_PRINT("%s on pchan %s\n", __func__, pchan->name);
+ DEG_debug_print_eval(__func__, pchan->name, pchan);
if (pchan->bone) {
invert_m4_m4(imat, pchan->bone->arm_mat);
mul_m4_m4m4(pchan->chan_mat, pchan->pose_mat, imat);
@@ -672,40 +693,61 @@ void BKE_pose_bone_done(const struct EvaluationContext *UNUSED(eval_ctx),
void BKE_pose_iktree_evaluate(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
- bPoseChannel *rootchan)
+ int rootchan_index)
{
- float ctime = BKE_scene_frame_get(scene); /* not accurate... */
- DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, rootchan->name);
+ bPoseChannel *rootchan = pose_pchan_get_indexed(ob, rootchan_index);
+ DEG_debug_print_eval_subdata(
+ __func__, ob->id.name, ob, "rootchan", rootchan->name, rootchan);
+ BLI_assert(ob->type == OB_ARMATURE);
+ const float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ bArmature *arm = (bArmature *)ob->data;
+ if (arm->flag & ARM_RESTPOS) {
+ return;
+ }
BIK_execute_tree(eval_ctx, scene, ob, rootchan, ctime);
}
void BKE_pose_splineik_evaluate(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
- bPoseChannel *rootchan)
+ int rootchan_index)
+
{
- float ctime = BKE_scene_frame_get(scene); /* not accurate... */
- DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, rootchan->name);
+ bPoseChannel *rootchan = pose_pchan_get_indexed(ob, rootchan_index);
+ DEG_debug_print_eval_subdata(
+ __func__, ob->id.name, ob, "rootchan", rootchan->name, rootchan);
+ BLI_assert(ob->type == OB_ARMATURE);
+ const float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ bArmature *arm = (bArmature *)ob->data;
+ if (arm->flag & ARM_RESTPOS) {
+ return;
+ }
BKE_splineik_execute_tree(eval_ctx, scene, ob, rootchan, ctime);
}
void BKE_pose_eval_flush(const struct EvaluationContext *UNUSED(eval_ctx),
Scene *scene,
- Object *ob,
- bPose *UNUSED(pose))
+ Object *ob)
{
+ bPose *pose = ob->pose;
+ BLI_assert(pose != NULL);
+
float ctime = BKE_scene_frame_get(scene); /* not accurate... */
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
BLI_assert(ob->type == OB_ARMATURE);
- /* 6. release the IK tree */
+ /* release the IK tree */
BIK_release_tree(scene, ob, ctime);
+
+ BLI_assert(pose->chan_array != NULL);
+ MEM_freeN(pose->chan_array);
+ pose->chan_array = NULL;
}
void BKE_pose_eval_proxy_copy(const struct EvaluationContext *UNUSED(eval_ctx), Object *ob)
{
BLI_assert(ID_IS_LINKED(ob) && ob->proxy_from != NULL);
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) {
printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
ob->id.name + 2, ob->proxy_from->id.name + 2);
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 182b88c1c57..236b965ec34 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -45,6 +45,7 @@
#include "IMB_imbuf.h"
#include "IMB_moviecache.h"
+#include "BKE_addon.h"
#include "BKE_blender.h" /* own include */
#include "BKE_blender_version.h" /* own include */
#include "BKE_blendfile.h"
@@ -84,6 +85,10 @@ void BKE_blender_free(void)
BKE_main_free(G.main);
G.main = NULL;
+ if (G.log.file != NULL) {
+ fclose(G.log.file);
+ }
+
BKE_spacetypes_free(); /* after free main, it uses space callbacks */
IMB_exit();
@@ -133,6 +138,8 @@ void BKE_blender_globals_init(void)
#else
G.f &= ~G_SCRIPT_AUTOEXEC;
#endif
+
+ G.log.level = 1;
}
void BKE_blender_globals_clear(void)
@@ -202,11 +209,7 @@ static void userdef_free_addons(UserDef *userdef)
{
for (bAddon *addon = userdef->addons.first, *addon_next; addon; addon = addon_next) {
addon_next = addon->next;
- if (addon->prop) {
- IDP_FreeProperty(addon->prop);
- MEM_freeN(addon->prop);
- }
- MEM_freeN(addon);
+ BKE_addon_free(addon);
}
BLI_listbase_clear(&userdef->addons);
}
diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c
index b8f46756445..98482bcc8b1 100644
--- a/source/blender/blenkernel/intern/blender_undo.c
+++ b/source/blender/blenkernel/intern/blender_undo.c
@@ -42,27 +42,18 @@
#include "DNA_scene_types.h"
-#include "BLI_fileops.h"
-#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
-#include "IMB_imbuf.h"
-#include "IMB_moviecache.h"
-
#include "BKE_blender_undo.h" /* own include */
#include "BKE_blendfile.h"
#include "BKE_appdir.h"
-#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_image.h"
#include "BKE_main.h"
-#include "RE_pipeline.h"
#include "BLO_undofile.h"
-#include "BLO_readfile.h"
#include "BLO_writefile.h"
#include "DEG_depsgraph.h"
@@ -74,44 +65,22 @@
#define UNDO_DISK 0
-typedef struct UndoElem {
- struct UndoElem *next, *prev;
- char str[FILE_MAX];
- char name[BKE_UNDO_STR_MAX];
- MemFile memfile;
- uintptr_t undosize;
-} UndoElem;
-
-static ListBase undobase = {NULL, NULL};
-static UndoElem *curundo = NULL;
-
-/**
- * Avoid bad-level call to #WM_jobs_kill_all_except()
- */
-static void (*undo_wm_job_kill_callback)(struct bContext *C) = NULL;
-
-void BKE_undo_callback_wm_kill_jobs_set(void (*callback)(struct bContext *C))
-{
- undo_wm_job_kill_callback = callback;
-}
-
-static int read_undosave(bContext *C, UndoElem *uel)
+bool BKE_memfile_undo_decode(MemFileUndoData *mfu, bContext *C)
{
char mainstr[sizeof(G.main->name)];
int success = 0, fileflags;
- /* This is needed so undoing/redoing doesn't crash with threaded previews going */
- undo_wm_job_kill_callback(C);
-
BLI_strncpy(mainstr, G.main->name, sizeof(mainstr)); /* temporal store */
fileflags = G.fileflags;
G.fileflags |= G_FILE_NO_UI;
- if (UNDO_DISK)
- success = (BKE_blendfile_read(C, uel->str, NULL, 0) != BKE_BLENDFILE_READ_FAIL);
- else
- success = BKE_blendfile_read_from_memfile(C, &uel->memfile, NULL, 0);
+ if (UNDO_DISK) {
+ success = (BKE_blendfile_read(C, mfu->filename, NULL, 0) != BKE_BLENDFILE_READ_FAIL);
+ }
+ else {
+ success = BKE_blendfile_read_from_memfile(C, &mfu->memfile, NULL, 0);
+ }
/* restore */
BLI_strncpy(G.main->name, mainstr, sizeof(G.main->name)); /* restore */
@@ -125,283 +94,43 @@ static int read_undosave(bContext *C, UndoElem *uel)
return success;
}
-/* name can be a dynamic string */
-void BKE_undo_write(bContext *C, const char *name)
+MemFileUndoData *BKE_memfile_undo_encode(Main *bmain, MemFileUndoData *mfu_prev)
{
- uintptr_t maxmem, totmem, memused;
- int nr /*, success */ /* UNUSED */;
- UndoElem *uel;
-
- if ((U.uiflag & USER_GLOBALUNDO) == 0) {
- return;
- }
-
- if (U.undosteps == 0) {
- return;
- }
-
- /* remove all undos after (also when curundo == NULL) */
- while (undobase.last != curundo) {
- uel = undobase.last;
- BLI_remlink(&undobase, uel);
- BLO_memfile_free(&uel->memfile);
- MEM_freeN(uel);
- }
-
- /* make new */
- curundo = uel = MEM_callocN(sizeof(UndoElem), "undo file");
- BLI_strncpy(uel->name, name, sizeof(uel->name));
- BLI_addtail(&undobase, uel);
-
- /* and limit amount to the maximum */
- nr = 0;
- uel = undobase.last;
- while (uel) {
- nr++;
- if (nr == U.undosteps) break;
- uel = uel->prev;
- }
- if (uel) {
- while (undobase.first != uel) {
- UndoElem *first = undobase.first;
- BLI_remlink(&undobase, first);
- /* the merge is because of compression */
- BLO_memfile_merge(&first->memfile, &first->next->memfile);
- MEM_freeN(first);
- }
- }
-
+ MemFileUndoData *mfu = MEM_callocN(sizeof(MemFileUndoData), __func__);
/* disk save version */
if (UNDO_DISK) {
static int counter = 0;
- char filepath[FILE_MAX];
+ char filename[FILE_MAX];
char numstr[32];
int fileflags = G.fileflags & ~(G_FILE_HISTORY); /* don't do file history on undo */
- /* calculate current filepath */
+ /* Calculate current filename. */
counter++;
counter = counter % U.undosteps;
BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter);
- BLI_make_file_string("/", filepath, BKE_tempdir_session(), numstr);
-
- /* success = */ /* UNUSED */ BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL);
-
- BLI_strncpy(curundo->str, filepath, sizeof(curundo->str));
- }
- else {
- MemFile *prevfile = NULL;
-
- if (curundo->prev) prevfile = &(curundo->prev->memfile);
-
- memused = MEM_get_memory_in_use();
- /* success = */ /* UNUSED */ BLO_write_file_mem(CTX_data_main(C), prevfile, &curundo->memfile, G.fileflags);
- curundo->undosize = MEM_get_memory_in_use() - memused;
- }
-
- if (U.undomemory != 0) {
- /* limit to maximum memory (afterwards, we can't know in advance) */
- totmem = 0;
- maxmem = ((uintptr_t)U.undomemory) * 1024 * 1024;
-
- /* keep at least two (original + other) */
- uel = undobase.last;
- while (uel && uel->prev) {
- totmem += uel->undosize;
- if (totmem > maxmem) break;
- uel = uel->prev;
- }
-
- if (uel) {
- if (uel->prev && uel->prev->prev)
- uel = uel->prev;
+ BLI_make_file_string("/", filename, BKE_tempdir_session(), numstr);
- while (undobase.first != uel) {
- UndoElem *first = undobase.first;
- BLI_remlink(&undobase, first);
- /* the merge is because of compression */
- BLO_memfile_merge(&first->memfile, &first->next->memfile);
- MEM_freeN(first);
- }
- }
- }
-}
-
-/* 1 = an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation */
-void BKE_undo_step(bContext *C, int step)
-{
+ /* success = */ /* UNUSED */ BLO_write_file(bmain, filename, fileflags, NULL, NULL);
- if (step == 0) {
- read_undosave(C, curundo);
- }
- else if (step == 1) {
- /* curundo should never be NULL, after restart or load file it should call undo_save */
- if (curundo == NULL || curundo->prev == NULL) {
- // XXX error("No undo available");
- }
- else {
- if (G.debug & G_DEBUG) printf("undo %s\n", curundo->name);
- curundo = curundo->prev;
- read_undosave(C, curundo);
- }
+ BLI_strncpy(mfu->filename, filename, sizeof(mfu->filename));
}
else {
- /* curundo has to remain current situation! */
-
- if (curundo == NULL || curundo->next == NULL) {
- // XXX error("No redo available");
- }
- else {
- read_undosave(C, curundo->next);
- curundo = curundo->next;
- if (G.debug & G_DEBUG) printf("redo %s\n", curundo->name);
- }
- }
-}
-
-void BKE_undo_reset(void)
-{
- UndoElem *uel;
-
- uel = undobase.first;
- while (uel) {
- BLO_memfile_free(&uel->memfile);
- uel = uel->next;
+ MemFile *prevfile = (mfu_prev) ? &(mfu_prev->memfile) : NULL;
+ /* success = */ /* UNUSED */ BLO_write_file_mem(bmain, prevfile, &mfu->memfile, G.fileflags);
+ mfu->undo_size = mfu->memfile.size;
}
- BLI_freelistN(&undobase);
- curundo = NULL;
-}
-
-/* based on index nr it does a restore */
-void BKE_undo_number(bContext *C, int nr)
-{
- curundo = BLI_findlink(&undobase, nr);
- BKE_undo_step(C, 0);
-}
-
-/* go back to the last occurance of name in stack */
-void BKE_undo_name(bContext *C, const char *name)
-{
- UndoElem *uel = BLI_rfindstring(&undobase, name, offsetof(UndoElem, name));
-
- if (uel && uel->prev) {
- curundo = uel->prev;
- BKE_undo_step(C, 0);
- }
-}
-
-/* name optional */
-bool BKE_undo_is_valid(const char *name)
-{
- if (name) {
- UndoElem *uel = BLI_rfindstring(&undobase, name, offsetof(UndoElem, name));
- return uel && uel->prev;
- }
+ bmain->is_memfile_undo_written = true;
- return undobase.last != undobase.first;
+ return mfu;
}
-/* get name of undo item, return null if no item with this index */
-/* if active pointer, set it to 1 if true */
-const char *BKE_undo_get_name(int nr, bool *r_active)
-{
- UndoElem *uel = BLI_findlink(&undobase, nr);
-
- if (r_active) *r_active = false;
-
- if (uel) {
- if (r_active && (uel == curundo)) {
- *r_active = true;
- }
- return uel->name;
- }
- return NULL;
-}
-
-/* return the name of the last item */
-const char *BKE_undo_get_name_last(void)
-{
- UndoElem *uel = undobase.last;
- return (uel ? uel->name : NULL);
-}
-
-/**
- * Saves .blend using undo buffer.
- *
- * \return success.
- */
-bool BKE_undo_save_file(const char *filename)
+void BKE_memfile_undo_free(MemFileUndoData *mfu)
{
- UndoElem *uel;
- MemFileChunk *chunk;
- int file, oflags;
-
- if ((U.uiflag & USER_GLOBALUNDO) == 0) {
- return false;
- }
-
- uel = curundo;
- if (uel == NULL) {
- fprintf(stderr, "No undo buffer to save recovery file\n");
- return false;
- }
-
- /* note: This is currently used for autosave and 'quit.blend', where _not_ following symlinks is OK,
- * however if this is ever executed explicitly by the user, we may want to allow writing to symlinks.
- */
-
- oflags = O_BINARY | O_WRONLY | O_CREAT | O_TRUNC;
-#ifdef O_NOFOLLOW
- /* use O_NOFOLLOW to avoid writing to a symlink - use 'O_EXCL' (CVE-2008-1103) */
- oflags |= O_NOFOLLOW;
-#else
- /* TODO(sergey): How to deal with symlinks on windows? */
-# ifndef _MSC_VER
-# warning "Symbolic links will be followed on undo save, possibly causing CVE-2008-1103"
-# endif
-#endif
- file = BLI_open(filename, oflags, 0666);
-
- if (file == -1) {
- fprintf(stderr, "Unable to save '%s': %s\n",
- filename, errno ? strerror(errno) : "Unknown error opening file");
- return false;
- }
-
- for (chunk = uel->memfile.chunks.first; chunk; chunk = chunk->next) {
- if (write(file, chunk->buf, chunk->size) != chunk->size) {
- break;
- }
- }
-
- close(file);
-
- if (chunk) {
- fprintf(stderr, "Unable to save '%s': %s\n",
- filename, errno ? strerror(errno) : "Unknown error writing file");
- return false;
- }
- return true;
-}
-
-/* sets curscene */
-Main *BKE_undo_get_main(Scene **r_scene)
-{
- Main *mainp = NULL;
- BlendFileData *bfd = BLO_read_from_memfile(G.main, G.main->name, &curundo->memfile, NULL, BLO_READ_SKIP_NONE);
-
- if (bfd) {
- mainp = bfd->main;
- if (r_scene) {
- *r_scene = bfd->curscene;
- }
-
- MEM_freeN(bfd);
- }
-
- return mainp;
+ BLO_memfile_free(&mfu->memfile);
+ MEM_freeN(mfu);
}
/** \} */
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index 8c78787c259..f440ce711ff 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -35,7 +35,7 @@
#include "MEM_guardedalloc.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_scene_types.h"
#include "BLI_rand.h"
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index 158c6c31432..e9a8de4469d 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -53,8 +53,8 @@
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_movieclip_types.h"
-#include "DNA_object_fluidsim.h"
-#include "DNA_object_force.h"
+#include "DNA_object_fluidsim_types.h"
+#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_sequence_types.h"
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 8d63c1cfb44..d82c1ca56fe 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -151,7 +151,7 @@ void BKE_brush_init(Brush *brush)
/**
* \note Resulting brush will have two users: one as a fake user, another is assumed to be used by the caller.
*/
-Brush *BKE_brush_add(Main *bmain, const char *name, short ob_mode)
+Brush *BKE_brush_add(Main *bmain, const char *name, const eObjectMode ob_mode)
{
Brush *brush;
@@ -164,7 +164,7 @@ Brush *BKE_brush_add(Main *bmain, const char *name, short ob_mode)
return brush;
}
-struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode)
+struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode)
{
Brush *brush;
diff --git a/source/blender/blenkernel/intern/bullet.c b/source/blender/blenkernel/intern/bullet.c
index 088031e16a7..c16c0f7af31 100644
--- a/source/blender/blenkernel/intern/bullet.c
+++ b/source/blender/blenkernel/intern/bullet.c
@@ -33,7 +33,7 @@
#include "MEM_guardedalloc.h"
/* types */
-#include "DNA_object_force.h" /* here is the softbody struct */
+#include "DNA_object_force_types.h" /* here is the softbody struct */
#include "BKE_bullet.h"
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index 775499304d4..cd2c7194237 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -411,7 +411,7 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree(
BMVert *eve = BM_vert_at_index(em->bm, i);
BLI_bvhtree_insert(tree, i, eve->co, 1);
}
- BLI_assert(BLI_bvhtree_get_size(tree) == verts_num_active);
+ BLI_assert(BLI_bvhtree_get_len(tree) == verts_num_active);
BLI_bvhtree_balance(tree);
}
@@ -440,7 +440,7 @@ static BVHTree *bvhtree_from_mesh_verts_create_tree(
}
BLI_bvhtree_insert(tree, i, vert[i].co, 1);
}
- BLI_assert(BLI_bvhtree_get_size(tree) == verts_num_active);
+ BLI_assert(BLI_bvhtree_get_len(tree) == verts_num_active);
BLI_bvhtree_balance(tree);
}
@@ -612,7 +612,7 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree(
BLI_bvhtree_insert(tree, i, co[0], 2);
}
- BLI_assert(BLI_bvhtree_get_size(tree) == edges_num_active);
+ BLI_assert(BLI_bvhtree_get_len(tree) == edges_num_active);
BLI_bvhtree_balance(tree);
}
@@ -829,7 +829,7 @@ static BVHTree *bvhtree_from_mesh_faces_create_tree(
BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
}
}
- BLI_assert(BLI_bvhtree_get_size(tree) == faces_num_active);
+ BLI_assert(BLI_bvhtree_get_len(tree) == faces_num_active);
BLI_bvhtree_balance(tree);
}
}
@@ -990,7 +990,7 @@ static BVHTree *bvhtree_from_editmesh_looptri_create_tree(
}
}
}
- BLI_assert(BLI_bvhtree_get_size(tree) == looptri_num_active);
+ BLI_assert(BLI_bvhtree_get_len(tree) == looptri_num_active);
BLI_bvhtree_balance(tree);
}
}
@@ -1032,7 +1032,7 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(
BLI_bvhtree_insert(tree, i, co[0], 3);
}
}
- BLI_assert(BLI_bvhtree_get_size(tree) == looptri_num_active);
+ BLI_assert(BLI_bvhtree_get_len(tree) == looptri_num_active);
BLI_bvhtree_balance(tree);
}
}
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index f8215668034..8f156e8f267 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -42,7 +42,6 @@
#include "BKE_animsys.h"
#include "BKE_cachefile.h"
-#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
@@ -181,7 +180,6 @@ void BKE_cachefile_update_frame(Main *bmain, Scene *scene, const float ctime, co
ABC_free_handle(cache_file->handle);
cache_file->handle = ABC_create_handle(filename, NULL);
#endif
- break;
}
}
}
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 869e312614e..8c4bced1563 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -48,7 +48,6 @@
#include "BKE_animsys.h"
#include "BKE_camera.h"
#include "BKE_object.h"
-#include "BKE_global.h"
#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
@@ -61,8 +60,6 @@
#include "MEM_guardedalloc.h"
-#include "GPU_compositing.h"
-
/****************************** Camera Datablock *****************************/
void BKE_camera_init(Camera *cam)
@@ -79,8 +76,6 @@ void BKE_camera_init(Camera *cam)
cam->flag |= CAM_SHOWPASSEPARTOUT;
cam->passepartalpha = 0.5f;
- GPU_fx_compositor_init_dof_settings(&cam->gpu_dof);
-
/* stereoscopy 3d */
cam->stereo.interocular_distance = 0.065f;
cam->stereo.convergence_distance = 30.f * 0.065f;
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index ea54548ab09..a6c6d360769 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -3307,7 +3307,7 @@ void CDDM_calc_edges_tessface(DerivedMesh *dm)
}
}
- numEdges = BLI_edgeset_size(eh);
+ numEdges = BLI_edgeset_len(eh);
/* write new edges into a temporary CustomData */
CustomData_reset(&edgeData);
@@ -3376,7 +3376,7 @@ void CDDM_calc_edges(DerivedMesh *dm)
}
}
- numEdges = BLI_edgehash_size(eh);
+ numEdges = BLI_edgehash_len(eh);
/* write new edges into a temporary CustomData */
CustomData_reset(&edgeData);
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 09b793629f7..339dcc4a62e 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -40,6 +40,8 @@
#include "BLI_edgehash.h"
#include "BLI_linklist.h"
+#include "DEG_depsgraph.h"
+
#include "BKE_cdderivedmesh.h"
#include "BKE_cloth.h"
#include "BKE_effect.h"
@@ -478,8 +480,6 @@ void clothModifier_do(ClothModifierData *clmd, const struct EvaluationContext *e
return;
}
- return;
-
/* if on second frame, write cache for first frame */
if (cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
BKE_ptcache_write(&pid, startframe);
@@ -639,7 +639,7 @@ void cloth_free_modifier_extern(ClothModifierData *clmd )
**/
static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*vertexCos)[3])
{
- unsigned int i = 0;
+ unsigned int i = 0;
Cloth *cloth = clmd->clothObject;
if (clmd->clothObject) {
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index ca77969ccaa..15fda8a9786 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -68,44 +68,67 @@ static SceneCollection *collection_master_from_id(const ID *owner_id)
}
/**
- * Add a collection to a collection ListBase and syncronize all render layers
- * The ListBase is NULL when the collection is to be added to the master collection
+ * The automatic/fallback name of a new collection.
*/
-SceneCollection *BKE_collection_add(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name_custom)
+void BKE_collection_new_name_get(ID *owner_id, SceneCollection *sc_parent, char *rname)
+{
+ SceneCollection *sc_master = collection_master_from_id(owner_id);
+ char *name;
+
+ if (sc_parent == sc_master) {
+ name = BLI_sprintfN("Collection %d", BLI_listbase_count(&sc_master->scene_collections) + 1);
+ }
+ else {
+ const int number = BLI_listbase_count(&sc_parent->scene_collections) + 1;
+ const int digits = integer_digits_i(number);
+ const int max_len = sizeof(sc_parent->name) - 1 /* NULL terminator */ - (1 + digits) /* " %d" */;
+ name = BLI_sprintfN("%.*s %d", max_len, sc_parent->name, number);
+ }
+
+ BLI_strncpy(rname, name, MAX_NAME);
+ MEM_freeN(name);
+}
+
+/**
+ * Add a new collection, but don't handle syncing with layer collections
+ */
+static SceneCollection *collection_add(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name_custom)
{
SceneCollection *sc_master = collection_master_from_id(owner_id);
SceneCollection *sc = MEM_callocN(sizeof(SceneCollection), "New Collection");
sc->type = type;
- const char *name = name_custom;
+ char name[MAX_NAME];
if (!sc_parent) {
sc_parent = sc_master;
}
- if (!name) {
- if (sc_parent == sc_master) {
- name = BLI_sprintfN("Collection %d", BLI_listbase_count(&sc_master->scene_collections) + 1);
- }
- else {
- const int number = BLI_listbase_count(&sc_parent->scene_collections) + 1;
- const int digits = integer_digits_i(number);
- const int max_len = sizeof(sc_parent->name)
- - 1 /* NULL terminator */
- - (1 + digits) /* " %d" */;
- name = BLI_sprintfN("%.*s %d", max_len, sc_parent->name, number);
- }
+ if (name_custom != NULL) {
+ BLI_strncpy(name, name_custom, MAX_NAME);
+ }
+ else {
+ BKE_collection_new_name_get(owner_id, sc_parent, name);
}
BLI_addtail(&sc_parent->scene_collections, sc);
- BKE_collection_rename((Scene *)owner_id, sc, name);
+ BKE_collection_rename(owner_id, sc, name);
- BKE_layer_sync_new_scene_collection(owner_id, sc_parent, sc);
+ return sc;
+}
- if (name != name_custom) {
- MEM_freeN((char *)name);
+/**
+ * Add a collection to a collection ListBase and syncronize all render layers
+ * The ListBase is NULL when the collection is to be added to the master collection
+ */
+SceneCollection *BKE_collection_add(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name_custom)
+{
+ if (sc_parent == NULL) {
+ sc_parent = BKE_collection_master(owner_id);
}
- return sc;
+ SceneCollection *scene_collection = collection_add(owner_id, sc_parent, type, name_custom);
+ BKE_layer_sync_new_scene_collection(owner_id, sc_parent, scene_collection);
+ return scene_collection;
}
/**
@@ -208,7 +231,7 @@ bool BKE_collection_remove(ID *owner_id, SceneCollection *sc)
ListBase collection_objects;
BLI_duplicatelist(&collection_objects, &sc->objects);
- FOREACH_SCENE_COLLECTION(owner_id, scene_collection_iter)
+ FOREACH_SCENE_COLLECTION_BEGIN(owner_id, scene_collection_iter)
{
if (scene_collection_iter == sc) {
continue;
@@ -226,7 +249,7 @@ bool BKE_collection_remove(ID *owner_id, SceneCollection *sc)
link = link_next;
}
}
- FOREACH_SCENE_COLLECTION_END
+ FOREACH_SCENE_COLLECTION_END;
for (LinkData *link = collection_objects.first; link; link = link->next) {
BKE_collection_object_add(owner_id, sc_master, link->data);
@@ -270,6 +293,43 @@ void BKE_collection_copy_data(SceneCollection *sc_dst, SceneCollection *sc_src,
}
}
+/**
+ * Makes a shallow copy of a SceneCollection
+ *
+ * Add a new collection in the same level as the old one, copy any nested collections
+ * but link the objects to the new collection (as oppose to copy them).
+ */
+SceneCollection *BKE_collection_duplicate(ID *owner_id, SceneCollection *scene_collection)
+{
+ SceneCollection *scene_collection_master = BKE_collection_master(owner_id);
+ SceneCollection *scene_collection_parent = find_collection_parent(scene_collection, scene_collection_master);
+
+ /* It's not allowed to copy the master collection. */
+ if (scene_collection_master == scene_collection) {
+ return NULL;
+ }
+
+ SceneCollection *scene_collection_new = collection_add(
+ owner_id,
+ scene_collection_parent,
+ scene_collection->type,
+ scene_collection->name);
+
+ if (scene_collection_new != scene_collection->next) {
+ BLI_remlink(&scene_collection_parent->scene_collections, scene_collection_new);
+ BLI_insertlinkafter(&scene_collection_parent->scene_collections, scene_collection, scene_collection_new);
+ }
+
+ BKE_collection_copy_data(scene_collection_new, scene_collection, 0);
+ BKE_layer_sync_new_scene_collection(owner_id, scene_collection_parent, scene_collection_new);
+
+ /* Make sure every linked instance of the new collection has the same values (flags, overrides, ...) as the
+ * corresponding original collection. */
+ BKE_layer_collection_sync_flags(owner_id, scene_collection_new, scene_collection);
+
+ return scene_collection_new;
+}
+
static SceneCollection *master_collection_from_id(const ID *owner_id)
{
switch (GS(owner_id->name)) {
@@ -298,9 +358,9 @@ static void collection_rename(const ID *owner_id, SceneCollection *sc, const cha
BLI_uniquename(&sc_parent->scene_collections, sc, DATA_("Collection"), '.', offsetof(SceneCollection, name), sizeof(sc->name));
}
-void BKE_collection_rename(const Scene *scene, SceneCollection *sc, const char *name)
+void BKE_collection_rename(const ID *owner_id, SceneCollection *sc, const char *name)
{
- collection_rename(&scene->id, sc, name);
+ collection_rename(owner_id, sc, name);
}
/**
@@ -343,7 +403,7 @@ static void collection_object_add(const ID *owner_id, SceneCollection *sc, Objec
*/
bool BKE_collection_object_add(const ID *owner_id, SceneCollection *sc, Object *ob)
{
- if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) {
+ if (BKE_collection_object_exists(sc, ob)) {
/* don't add the same object twice */
return false;
}
@@ -358,13 +418,13 @@ bool BKE_collection_object_add(const ID *owner_id, SceneCollection *sc, Object *
*/
void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst)
{
- FOREACH_SCENE_COLLECTION(scene, sc)
+ FOREACH_SCENE_COLLECTION_BEGIN(scene, sc)
{
if (BLI_findptr(&sc->objects, ob_src, offsetof(LinkData, data))) {
collection_object_add(&scene->id, sc, ob_dst);
}
}
- FOREACH_SCENE_COLLECTION_END
+ FOREACH_SCENE_COLLECTION_END;
for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
Base *base_src = BKE_view_layer_base_find(view_layer, ob_src);
@@ -411,13 +471,28 @@ bool BKE_collection_object_remove(Main *bmain, ID *owner_id, SceneCollection *sc
}
/**
- * Move object from a collection into another
+ * Remove object from all collections of scene
+ * \param scene_collection_skip: Don't remove base from this collection.
*/
-void BKE_collection_object_move(ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src, Object *ob)
+static bool collections_object_remove_ex(Main *bmain, ID *owner_id, Object *ob, const bool free_us,
+ SceneCollection *scene_collection_skip)
{
- if (BKE_collection_object_add(owner_id, sc_dst, ob)) {
- BKE_collection_object_remove(NULL, owner_id, sc_src, ob, false);
+ bool removed = false;
+ if (GS(owner_id->name) == ID_SCE) {
+ BKE_scene_remove_rigidbody_object((Scene *)owner_id, ob);
}
+ else {
+ BLI_assert(GS(owner_id->name) == ID_GR);
+ }
+
+ FOREACH_SCENE_COLLECTION_BEGIN(owner_id, sc)
+ {
+ if (sc != scene_collection_skip) {
+ removed |= BKE_collection_object_remove(bmain, owner_id, sc, ob, free_us);
+ }
+ }
+ FOREACH_SCENE_COLLECTION_END;
+ return removed;
}
/**
@@ -425,20 +500,72 @@ void BKE_collection_object_move(ID *owner_id, SceneCollection *sc_dst, SceneColl
*/
bool BKE_collections_object_remove(Main *bmain, ID *owner_id, Object *ob, const bool free_us)
{
- bool removed = false;
- if (GS(owner_id->name) == ID_SCE) {
- BKE_scene_remove_rigidbody_object((Scene *)owner_id, ob);
+ return collections_object_remove_ex(bmain, owner_id, ob, free_us, NULL);
+}
+
+/**
+ * Move object from a collection into another
+ *
+ * If source collection is NULL move it from all the existing collections.
+ */
+void BKE_collection_object_move(ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src, Object *ob)
+{
+ /* In both cases we first add the object, then remove it from the other collections.
+ * Otherwise we lose the original base and whether it was active and selected. */
+ if (sc_src != NULL) {
+ if (BKE_collection_object_add(owner_id, sc_dst, ob)) {
+ BKE_collection_object_remove(NULL, owner_id, sc_src, ob, false);
+ }
}
else {
- BLI_assert(GS(owner_id->name) == ID_GR);
+ /* Adding will fail if object is already in collection.
+ * However we still need to remove it from the other collections. */
+ BKE_collection_object_add(owner_id, sc_dst, ob);
+ collections_object_remove_ex(NULL, owner_id, ob, false, sc_dst);
+ }
+}
+
+/**
+ * Whether the object is directly inside the collection.
+ */
+bool BKE_collection_object_exists(struct SceneCollection *scene_collection, struct Object *ob)
+{
+ if (BLI_findptr(&scene_collection->objects, ob, offsetof(LinkData, data))) {
+ return true;
}
+ return false;
+}
- FOREACH_SCENE_COLLECTION(owner_id, sc)
+static SceneCollection *scene_collection_from_index_recursive(SceneCollection *scene_collection, const int index, int *index_current)
+{
+ if (index == (*index_current)) {
+ return scene_collection;
+ }
+
+ (*index_current)++;
+
+ for (SceneCollection *scene_collection_iter = scene_collection->scene_collections.first;
+ scene_collection_iter != NULL;
+ scene_collection_iter = scene_collection_iter->next)
{
- removed |= BKE_collection_object_remove(bmain, owner_id, sc, ob, free_us);
+ SceneCollection *nested = scene_collection_from_index_recursive(scene_collection_iter, index, index_current);
+ if (nested != NULL) {
+ return nested;
+ }
}
- FOREACH_SCENE_COLLECTION_END
- return removed;
+ return NULL;
+}
+
+/**
+ * Return Scene Collection for a given index.
+ *
+ * The index is calculated from top to bottom counting the children before the siblings.
+ */
+SceneCollection *BKE_collection_from_index(Scene *scene, const int index)
+{
+ int index_current = 0;
+ SceneCollection *master_collection = BKE_collection_master(&scene->id);
+ return scene_collection_from_index_recursive(master_collection, index, &index_current);
}
static void layer_collection_sync(LayerCollection *lc_dst, LayerCollection *lc_src)
@@ -460,6 +587,33 @@ static void layer_collection_sync(LayerCollection *lc_dst, LayerCollection *lc_s
}
/**
+ * Select all the objects in this SceneCollection (and its nested collections) for this ViewLayer.
+ * Return true if any object was selected.
+ */
+bool BKE_collection_objects_select(ViewLayer *view_layer, SceneCollection *scene_collection)
+{
+ LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection(view_layer, scene_collection);
+ if (layer_collection != NULL) {
+ BKE_layer_collection_objects_select(layer_collection);
+ return true;
+ }
+ else {
+ /* Slower approach, we need to iterate over all the objects and for each one we see if there is a base. */
+ bool changed = false;
+ for (LinkData *link = scene_collection->objects.first; link; link = link->next) {
+ Base *base = BKE_view_layer_base_find(view_layer, link->data);
+ if (base != NULL) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
+ base->flag |= BASE_SELECTED;
+ changed = true;
+ }
+ }
+ }
+ return changed;
+ }
+}
+
+/**
* Leave only the master collection in, remove everything else.
* @param group
*/
@@ -505,11 +659,11 @@ Group *BKE_collection_group_create(Main *bmain, Scene *scene, LayerCollection *l
sc_dst = BKE_collection_add(&group->id, NULL, COLLECTION_TYPE_GROUP_INTERNAL, sc_src->name);
BKE_collection_copy_data(sc_dst, sc_src, 0);
- FOREACH_SCENE_COLLECTION(&group->id, sc_group)
+ FOREACH_SCENE_COLLECTION_BEGIN(&group->id, sc_group)
{
sc_group->type = COLLECTION_TYPE_GROUP_INTERNAL;
}
- FOREACH_SCENE_COLLECTION_END
+ FOREACH_SCENE_COLLECTION_END;
lc_dst = BKE_collection_link(group->view_layer, sc_dst);
layer_collection_sync(lc_dst, lc_src);
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index 2f80fbbec46..ee3c38b9282 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -36,7 +36,7 @@
#include "DNA_effect_types.h"
#include "DNA_group_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_scene_types.h"
#include "DNA_meshdata_types.h"
@@ -180,8 +180,8 @@ static void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3
/* dot_v3v3 */
#define INPR(v1, v2) ( (v1)[0] * (v2)[0] + (v1)[1] * (v2)[1] + (v1)[2] * (v2)[2])
- double tempV1[3], tempV2[3], tempV4[3];
- double a, b, c, d, e, f;
+ double tempV1[3], tempV2[3], tempV4[3];
+ double a, b, c, d, e, f;
VECSUB ( tempV1, p1, p3 );
VECSUB ( tempV2, p2, p3 );
@@ -506,11 +506,11 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned
Group *group= ob->dup_group;
/* add objects */
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
add_collision_object(objs, numobj, maxobj, object, self, level+1, modifier_type);
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
}
@@ -527,11 +527,11 @@ Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, unsi
/* gather all collision objects */
if (group) {
/* use specified group */
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
add_collision_object(&objs, &numobj, &maxobj, object, self, level, modifier_type);
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
else {
Scene *sce_iter;
@@ -584,11 +584,11 @@ static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self,
Group *group= ob->dup_group;
/* add objects */
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
add_collider_cache_object(objs, object, self, level+1);
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
}
@@ -598,11 +598,11 @@ ListBase *get_collider_cache(Scene *scene, Object *self, Group *group)
/* add object in same layer in scene */
if (group) {
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
add_collider_cache_object(&objs, object, self, 0);
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
else {
Scene *sce_iter;
diff --git a/source/blender/blenkernel/intern/colorband.c b/source/blender/blenkernel/intern/colorband.c
index d35e797ddac..f72d4df725a 100644
--- a/source/blender/blenkernel/intern/colorband.c
+++ b/source/blender/blenkernel/intern/colorband.c
@@ -210,7 +210,7 @@ static void colorband_init_from_table_rgba_resample(
while ((carr_len > 1 && !BLI_heap_is_empty(heap)) &&
((carr_len >= MAXCOLORBAND) || (BLI_heap_node_value(BLI_heap_top(heap)) <= eps_2x)))
{
- c = BLI_heap_popmin(heap);
+ c = BLI_heap_pop_min(heap);
struct ColorResampleElem *c_next = c->next, *c_prev = c->prev;
c_prev->next = c_next;
c_next->prev = c_prev;
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index b8dc7944a75..b070ccdd4eb 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -1917,14 +1917,15 @@ static void samevolume_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *
bSameVolumeConstraint *data = con->data;
float volume = data->volume;
- float fac = 1.0f;
+ float fac = 1.0f, total_scale;
float obsize[3];
mat4_to_size(obsize, cob->matrix);
/* calculate normalizing scale factor for non-essential values */
- if (obsize[data->flag] != 0)
- fac = sqrtf(volume / obsize[data->flag]);
+ total_scale = obsize[0] * obsize[1] * obsize[2];
+ if (total_scale != 0)
+ fac = sqrtf(volume / total_scale);
/* apply scaling factor to the channels not being kept */
switch (data->flag) {
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 09823a8b463..809db09eb86 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -997,7 +997,7 @@ SceneCollection *CTX_data_scene_collection(const bContext *C)
return BKE_collection_master(&scene->id);
}
-int CTX_data_mode_enum_ex(const Object *obedit, const Object *ob)
+int CTX_data_mode_enum_ex(const Object *obedit, const Object *ob, const eObjectMode object_mode)
{
// Object *obedit = CTX_data_edit_object(C);
if (obedit) {
@@ -1023,12 +1023,12 @@ int CTX_data_mode_enum_ex(const Object *obedit, const Object *ob)
else {
// Object *ob = CTX_data_active_object(C);
if (ob) {
- if (ob->mode & OB_MODE_POSE) return CTX_MODE_POSE;
- else if (ob->mode & OB_MODE_SCULPT) return CTX_MODE_SCULPT;
- else if (ob->mode & OB_MODE_WEIGHT_PAINT) return CTX_MODE_PAINT_WEIGHT;
- else if (ob->mode & OB_MODE_VERTEX_PAINT) return CTX_MODE_PAINT_VERTEX;
- else if (ob->mode & OB_MODE_TEXTURE_PAINT) return CTX_MODE_PAINT_TEXTURE;
- else if (ob->mode & OB_MODE_PARTICLE_EDIT) return CTX_MODE_PARTICLE;
+ if (object_mode & OB_MODE_POSE) return CTX_MODE_POSE;
+ else if (object_mode & OB_MODE_SCULPT) return CTX_MODE_SCULPT;
+ else if (object_mode & OB_MODE_WEIGHT_PAINT) return CTX_MODE_PAINT_WEIGHT;
+ else if (object_mode & OB_MODE_VERTEX_PAINT) return CTX_MODE_PAINT_VERTEX;
+ else if (object_mode & OB_MODE_TEXTURE_PAINT) return CTX_MODE_PAINT_TEXTURE;
+ else if (object_mode & OB_MODE_PARTICLE_EDIT) return CTX_MODE_PARTICLE;
}
}
@@ -1039,7 +1039,7 @@ int CTX_data_mode_enum(const bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
Object *obact = obedit ? NULL : CTX_data_active_object(C);
- return CTX_data_mode_enum_ex(obedit, obact);
+ return CTX_data_mode_enum_ex(obedit, obact, obact ? obact->mode : OB_MODE_OBJECT);
}
/* would prefer if we can use the enum version below over this one - Campbell */
@@ -1276,8 +1276,8 @@ void CTX_data_eval_ctx(const bContext *C, EvaluationContext *eval_ctx)
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- RenderEngineType *engine_type = CTX_data_engine_type(C);
- DEG_evaluation_context_init_from_scene(eval_ctx,
- scene, view_layer, engine_type,
- DAG_EVAL_VIEWPORT);
+ DEG_evaluation_context_init_from_scene(
+ eval_ctx,
+ scene, view_layer,
+ DAG_EVAL_VIEWPORT);
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 2a27bad0fb5..0c4dbdf7763 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -5258,9 +5258,7 @@ void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *t
void BKE_curve_eval_geometry(const EvaluationContext *UNUSED(eval_ctx),
Curve *curve)
{
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s\n", __func__, curve->id.name);
- }
+ DEG_debug_print_eval(__func__, curve->id.name, curve);
if (curve->bb == NULL || (curve->bb->flag & BOUNDBOX_DIRTY)) {
BKE_curve_texspace_calc(curve);
}
diff --git a/source/blender/blenkernel/intern/curve_decimate.c b/source/blender/blenkernel/intern/curve_decimate.c
index 7983c63c99d..1a6c4714afd 100644
--- a/source/blender/blenkernel/intern/curve_decimate.c
+++ b/source/blender/blenkernel/intern/curve_decimate.c
@@ -159,7 +159,7 @@ static void curve_decimate(
struct Knot *k;
{
- struct Removal *r = BLI_heap_popmin(heap);
+ struct Removal *r = BLI_heap_pop_min(heap);
k = &knots[r->knot_index];
k->heap_node = NULL;
k->prev->handles[1] = r->handles[0];
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 15a520fe8ce..ffa4e652056 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -299,7 +299,10 @@ bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, i
}
/* ****************** make displists ********************* */
-
+#ifdef __INTEL_COMPILER
+/* ICC with the optimization -02 causes crashes. */
+# pragma intel optimization_level 1
+#endif
static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase,
const bool for_render, const bool use_render_resolution)
{
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 2591c3c3c47..ee678dd4c41 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -54,7 +54,7 @@
#include "BKE_animsys.h"
#include "BKE_armature.h"
-#include "BKE_bvhutils.h" /* bvh tree */
+#include "BKE_bvhutils.h" /* bvh tree */
#include "BKE_colorband.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_constraint.h"
@@ -3348,7 +3348,7 @@ typedef struct BrushMaterials {
/* Initialize materials for brush object:
* Calculates inverse matrices for linked objects, updates
* volume caches etc. */
-static void dynamicPaint_updateBrushMaterials(Object *brushOb, Material *ui_mat, Scene *scene, BrushMaterials *bMats)
+static void dynamicPaint_updateBrushMaterials(const EvaluationContext *eval_ctx, Object *brushOb, Material *ui_mat, Scene *scene, BrushMaterials *bMats)
{
/* Calculate inverse transformation matrix
* for this object */
@@ -3363,13 +3363,13 @@ static void dynamicPaint_updateBrushMaterials(Object *brushOb, Material *ui_mat,
if (tot) {
bMats->ob_mats = MEM_callocN(sizeof(Material *) * (tot), "BrushMaterials");
for (i = 0; i < tot; i++) {
- bMats->ob_mats[i] = RE_sample_material_init(give_current_material(brushOb, (i + 1)), scene);
+ bMats->ob_mats[i] = RE_sample_material_init(eval_ctx, give_current_material(brushOb, (i + 1)), scene);
}
}
bMats->tot = tot;
}
else {
- bMats->mat = RE_sample_material_init(ui_mat, scene);
+ bMats->mat = RE_sample_material_init(eval_ctx, ui_mat, scene);
}
}
@@ -4516,7 +4516,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface,
*/
tree = BLI_kdtree_new(psys->totpart);
- /* loop through particles and insert valid ones to the tree */
+ /* loop through particles and insert valid ones to the tree */
p = 0;
for (ParticleData *pa = psys->particles; p < psys->totpart; p++, pa++) {
/* Proceed only if particle is active */
@@ -4555,7 +4555,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface,
}
/* begin thread safe malloc */
- BLI_begin_threaded_malloc();
+ BLI_threaded_malloc_begin();
/* only continue if particle bb is close enough to canvas bb */
if (boundsIntersectDist(&grid->grid_bounds, &part_bb, range)) {
@@ -4590,7 +4590,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface,
&settings);
}
}
- BLI_end_threaded_malloc();
+ BLI_threaded_malloc_end();
BLI_kdtree_free(tree);
return 1;
@@ -6087,7 +6087,7 @@ static int dynamicPaint_doStep(const struct EvaluationContext *eval_ctx, Scene *
}
/* Prepare materials if required */
if (brush_usesMaterial(brush, scene))
- dynamicPaint_updateBrushMaterials(brushObj, brush->mat, scene, &bMats);
+ dynamicPaint_updateBrushMaterials(eval_ctx, brushObj, brush->mat, scene, &bMats);
/* Apply brush on the surface depending on it's collision type */
if (brush->psys && brush->psys->part &&
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index 0491cbd21f0..2018962eb62 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -44,7 +44,7 @@
#include "atomic_ops.h"
#include "BLI_math.h"
-#include "BLI_jitter.h"
+#include "BLI_jitter_2d.h"
#include "BLI_bitmap.h"
#include "BLI_task.h"
diff --git a/source/blender/blenkernel/intern/editlattice.c b/source/blender/blenkernel/intern/editlattice.c
new file mode 100644
index 00000000000..cef3c970c7a
--- /dev/null
+++ b/source/blender/blenkernel/intern/editlattice.c
@@ -0,0 +1,147 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/editlattice.c
+ * \ingroup bke
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_object_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_curve_types.h"
+
+#include "BLI_math_vector.h"
+#include "BLI_listbase.h"
+
+#include "BKE_deform.h"
+#include "BKE_key.h"
+
+#include "BKE_editlattice.h" /* own include */
+
+void BKE_editlattice_free(Object *ob)
+{
+ Lattice *lt = ob->data;
+
+ if (lt->editlatt) {
+ Lattice *editlt = lt->editlatt->latt;
+
+ if (editlt->def) {
+ MEM_freeN(editlt->def);
+ }
+ if (editlt->dvert) {
+ BKE_defvert_array_free(editlt->dvert, editlt->pntsu * editlt->pntsv * editlt->pntsw);
+ }
+ MEM_freeN(editlt);
+ MEM_freeN(lt->editlatt);
+
+ lt->editlatt = NULL;
+ }
+}
+
+void BKE_editlattice_make(Object *obedit)
+{
+ Lattice *lt = obedit->data;
+ KeyBlock *actkey;
+
+ BKE_editlattice_free(obedit);
+
+ actkey = BKE_keyblock_from_object(obedit);
+ if (actkey) {
+ BKE_keyblock_convert_to_lattice(actkey, lt);
+ }
+ lt->editlatt = MEM_callocN(sizeof(EditLatt), "editlatt");
+ lt->editlatt->latt = MEM_dupallocN(lt);
+ lt->editlatt->latt->def = MEM_dupallocN(lt->def);
+
+ if (lt->dvert) {
+ int tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ lt->editlatt->latt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
+ BKE_defvert_array_copy(lt->editlatt->latt->dvert, lt->dvert, tot);
+ }
+
+ if (lt->key) {
+ lt->editlatt->shapenr = obedit->shapenr;
+ }
+}
+
+void BKE_editlattice_load(Object *obedit)
+{
+ Lattice *lt, *editlt;
+ KeyBlock *actkey;
+ BPoint *bp;
+ float *fp;
+ int tot;
+
+ lt = obedit->data;
+ editlt = lt->editlatt->latt;
+
+ if (lt->editlatt->shapenr) {
+ actkey = BLI_findlink(&lt->key->block, lt->editlatt->shapenr - 1);
+
+ /* active key: vertices */
+ tot = editlt->pntsu * editlt->pntsv * editlt->pntsw;
+
+ if (actkey->data) {
+ MEM_freeN(actkey->data);
+ }
+
+ fp = actkey->data = MEM_callocN(lt->key->elemsize * tot, "actkey->data");
+ actkey->totelem = tot;
+
+ bp = editlt->def;
+ while (tot--) {
+ copy_v3_v3(fp, bp->vec);
+ fp += 3;
+ bp++;
+ }
+ }
+ else {
+ MEM_freeN(lt->def);
+
+ lt->def = MEM_dupallocN(editlt->def);
+
+ lt->flag = editlt->flag;
+
+ lt->pntsu = editlt->pntsu;
+ lt->pntsv = editlt->pntsv;
+ lt->pntsw = editlt->pntsw;
+
+ lt->typeu = editlt->typeu;
+ lt->typev = editlt->typev;
+ lt->typew = editlt->typew;
+ lt->actbp = editlt->actbp;
+ }
+
+ if (lt->dvert) {
+ BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
+ lt->dvert = NULL;
+ }
+
+ if (editlt->dvert) {
+ tot = lt->pntsu * lt->pntsv * lt->pntsw;
+
+ lt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
+ BKE_defvert_array_copy(lt->dvert, editlt->dvert, tot);
+ }
+}
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 16124fb4777..b54093555f5 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -42,7 +42,7 @@
#include "DNA_listBase.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_particle_types.h"
#include "DNA_texture_types.h"
#include "DNA_scene_types.h"
@@ -221,7 +221,8 @@ ListBase *pdInitEffectors(
if (weights->group) {
view_layer = weights->group->view_layer;
}
- else if (eval_ctx) {
+ /* TODO(mai): the check for view_layer shouldnt be needed, remove when render engine api is updated for this */
+ else if (eval_ctx && eval_ctx->view_layer) {
view_layer = eval_ctx->view_layer;
}
else {
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 9c85a26b58a..905f103250a 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -804,7 +804,7 @@ void bezt_add_to_cfra_elem(ListBase *lb, BezTriple *bezt)
for (ce = lb->first; ce; ce = ce->next) {
/* double key? */
- if (ce->cfra == bezt->vec[1][0]) {
+ if (IS_EQT(ce->cfra, bezt->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
if (bezt->f2 & SELECT) ce->sel = bezt->f2;
return;
}
@@ -1590,11 +1590,9 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
return 0.0f;
}
else if (dtar->transChan >= DTAR_TRANSCHAN_SCALEX) {
- /* extract scale, and choose the right axis */
- float scale[3];
-
- mat4_to_size(scale, mat);
- return scale[dtar->transChan - DTAR_TRANSCHAN_SCALEX];
+ /* Extract scale, and choose the right axis,
+ * inline 'mat4_to_size'. */
+ return len_v3(mat[dtar->transChan - DTAR_TRANSCHAN_SCALEX]);
}
else if (dtar->transChan >= DTAR_TRANSCHAN_ROTX) {
/* extract rotation as eulers (if needed)
diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c
index 12b9abc6d03..d0d3317b477 100644
--- a/source/blender/blenkernel/intern/fluidsim.c
+++ b/source/blender/blenkernel/intern/fluidsim.c
@@ -40,8 +40,8 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_object_fluidsim.h"
-#include "DNA_object_force.h" // for pointcache
+#include "DNA_object_fluidsim_types.h"
+#include "DNA_object_force_types.h" // for pointcache
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
@@ -54,7 +54,6 @@
#include "BKE_customdata.h"
#include "BKE_DerivedMesh.h"
#include "BKE_fluidsim.h"
-#include "BKE_global.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index a314cc0a131..5545eba8764 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -1080,8 +1080,13 @@ makebreak:
float distfac, imat[4][4], imat3[3][3], cmat[3][3];
float minx, maxx, miny, maxy;
float timeofs, sizefac;
-
- invert_m4_m4(imat, ob->obmat);
+
+ if (ob != NULL) {
+ invert_m4_m4(imat, ob->obmat);
+ }
+ else {
+ unit_m4(imat);
+ }
copy_m3_m4(imat3, imat);
copy_m3_m4(cmat, cu->textoncurve->obmat);
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index ca6d92efa80..7566d370c45 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -55,7 +55,7 @@
#include "BKE_object.h"
#include "BKE_scene.h"
-#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
+#include "DEG_depsgraph.h"
/** Free (or release) any data used by this group (does not free the group itself). */
void BKE_group_free(Group *group)
@@ -213,13 +213,13 @@ static bool group_object_cyclic_check_internal(Object *object, Group *group)
if (dup_group == group)
return true;
else {
- FOREACH_GROUP_OBJECT(dup_group, group_object)
+ FOREACH_GROUP_OBJECT_BEGIN(dup_group, group_object)
{
if (group_object_cyclic_check_internal(group_object, dup_group)) {
return true;
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
/* un-flag the object, it's allowed to have the same group multiple times in parallel */
@@ -278,13 +278,13 @@ Group *BKE_group_object_find(Group *group, Object *ob)
bool BKE_group_is_animated(Group *group, Object *UNUSED(parent))
{
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
if (object->proxy) {
return true;
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
return false;
}
@@ -369,45 +369,21 @@ void BKE_group_handle_recalc_and_update(const struct EvaluationContext *eval_ctx
#endif
{
/* only do existing tags, as set by regular depsgraph */
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
if (object->id.recalc & ID_RECALC_ALL) {
BKE_object_handle_update(eval_ctx, scene, object);
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
}
/* ******** Dependency graph evaluation ******** */
-static void group_eval_layer_collections(
- const struct EvaluationContext *eval_ctx,
- Group *group,
- ListBase *layer_collections,
- LayerCollection *parent_layer_collection)
-{
- BLI_LISTBASE_FOREACH (LayerCollection *, layer_collection, layer_collections) {
- /* Evaluate layer collection itself. */
- BKE_layer_eval_layer_collection(eval_ctx,
- layer_collection,
- parent_layer_collection);
- /* Evaluate nested collections. */
- group_eval_layer_collections(eval_ctx,
- group,
- &layer_collection->layer_collections,
- layer_collection);
- }
-}
-
void BKE_group_eval_view_layers(const struct EvaluationContext *eval_ctx,
Group *group)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, group->id.name, group);
- BKE_layer_eval_layer_collection_pre(eval_ctx, &group->id, group->view_layer);
- group_eval_layer_collections(eval_ctx,
- group,
- &group->view_layer->layer_collections,
- NULL);
- BKE_layer_eval_layer_collection_post(eval_ctx, group->view_layer);
+ DEG_debug_print_eval(__func__, group->id.name, group);
+ BKE_layer_eval_view_layer(eval_ctx, &group->id, group->view_layer);
}
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index a407fd0bae8..f3ff2c4425a 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -433,23 +433,28 @@ void BKE_previewimg_ensure(PreviewImage *prv, const int size)
}
}
-void BKE_icon_changed(int id)
+void BKE_icon_changed(const int icon_id)
{
Icon *icon = NULL;
- if (!id || G.background) return;
+ if (!icon_id || G.background) return;
- icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(id));
+ icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(icon_id));
if (icon) {
- PreviewImage *prv = BKE_previewimg_id_ensure((ID *)icon->obj);
+ /* We *only* expect ID-tied icons here, not non-ID icon/preview! */
+ BLI_assert(icon->type != 0);
+
+ /* Do not enforce creation of previews for valid ID types using BKE_previewimg_id_ensure() here ,
+ * we only want to ensure *existing* preview images are properly tagged as changed/invalid, that's all. */
+ PreviewImage **p_prv = BKE_previewimg_id_get_p((ID *)icon->obj);
- /* all previews changed */
- if (prv) {
+ /* If we have previews, they all are now invalid changed. */
+ if (p_prv && *p_prv) {
int i;
for (i = 0; i < NUM_ICON_SIZES; ++i) {
- prv->flag[i] |= PRV_CHANGED;
- prv->changed_timestamp[i]++;
+ (*p_prv)->flag[i] |= PRV_CHANGED;
+ (*p_prv)->changed_timestamp[i]++;
}
}
}
@@ -549,7 +554,7 @@ int BKE_icon_preview_ensure(ID *id, PreviewImage *preview)
return preview->icon_id;
}
-Icon *BKE_icon_get(int icon_id)
+Icon *BKE_icon_get(const int icon_id)
{
Icon *icon = NULL;
@@ -563,7 +568,7 @@ Icon *BKE_icon_get(int icon_id)
return icon;
}
-void BKE_icon_set(int icon_id, struct Icon *icon)
+void BKE_icon_set(const int icon_id, struct Icon *icon)
{
void **val_p;
@@ -586,7 +591,7 @@ void BKE_icon_id_delete(struct ID *id)
/**
* Remove icon and free data.
*/
-void BKE_icon_delete(int icon_id)
+void BKE_icon_delete(const int icon_id)
{
Icon *icon;
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 33a665ba06e..87e5ed8cc1e 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -905,9 +905,10 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is
if (prop1->len != prop2->len)
return false;
- for (i = 0; i < prop1->len; i++)
- if (!IDP_EqualsProperties(&array1[i], &array2[i]))
+ for (i = 0; i < prop1->len; i++) {
+ if (!IDP_EqualsProperties_ex(&array1[i], &array2[i], is_strict))
return false;
+ }
return true;
}
case IDP_ID:
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index d720dc41abf..28245f9a4d8 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -46,6 +46,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "IMB_moviecache.h"
+#include "IMB_metadata.h"
#ifdef WITH_OPENEXR
# include "intern/openexr/openexr_multi.h"
@@ -152,7 +153,7 @@ static void imagecache_put(Image *image, int index, ImBuf *ibuf)
if (image->cache == NULL) {
// char cache_name[64];
- // BLI_snprintf(cache_name, sizeof(cache_name), "Image Datablock %s", image->id.name);
+ // SNPRINTF(cache_name, "Image Datablock %s", image->id.name);
image->cache = IMB_moviecache_create("Image Datablock Cache", sizeof(ImageCacheKey),
imagecache_hashhash, imagecache_hashcmp);
@@ -437,7 +438,7 @@ static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src)
BLI_listbase_clear(lb_dst);
for (imapf_src = lb_src->first; imapf_src; imapf_src = imapf_src->next) {
ImagePackedFile *imapf_dst = MEM_mallocN(sizeof(ImagePackedFile), "Image Packed Files (copy)");
- BLI_strncpy(imapf_dst->filepath, imapf_src->filepath, sizeof(imapf_dst->filepath));
+ STRNCPY(imapf_dst->filepath, imapf_src->filepath);
if (imapf_src->packedfile)
imapf_dst->packedfile = dupPackedFile(imapf_src->packedfile);
@@ -593,7 +594,7 @@ Image *BKE_image_load(Main *bmain, const char *filepath)
int file;
char str[FILE_MAX];
- BLI_strncpy(str, filepath, sizeof(str));
+ STRNCPY(str, filepath);
BLI_path_abs(str, bmain->name);
/* exists? */
@@ -603,7 +604,7 @@ Image *BKE_image_load(Main *bmain, const char *filepath)
close(file);
ima = image_alloc(bmain, BLI_path_basename(filepath), IMA_SRC_FILE, IMA_TYPE_IMAGE);
- BLI_strncpy(ima->name, filepath, sizeof(ima->name));
+ STRNCPY(ima->name, filepath);
if (BLI_testextensie_array(filepath, imb_ext_movie))
ima->source = IMA_SRC_MOVIE;
@@ -622,13 +623,13 @@ Image *BKE_image_load_exists_ex(const char *filepath, bool *r_exists)
Image *ima;
char str[FILE_MAX], strtest[FILE_MAX];
- BLI_strncpy(str, filepath, sizeof(str));
+ STRNCPY(str, filepath);
BLI_path_abs(str, G.main->name);
/* first search an identical filepath */
for (ima = G.main->image.first; ima; ima = ima->id.next) {
if (ima->source != IMA_SRC_VIEWER && ima->source != IMA_SRC_GENERATED) {
- BLI_strncpy(strtest, ima->name, sizeof(ima->name));
+ STRNCPY(strtest, ima->name);
BLI_path_abs(strtest, ID_BLEND_PATH(G.main, &ima->id));
if (BLI_path_cmp(strtest, str) == 0) {
@@ -669,7 +670,7 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char
if (colorspace_settings->name[0] == '\0') {
const char *colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_FLOAT);
- BLI_strncpy(colorspace_settings->name, colorspace, sizeof(colorspace_settings->name));
+ STRNCPY(colorspace_settings->name, colorspace);
}
if (ibuf != NULL) {
@@ -683,7 +684,7 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char
if (colorspace_settings->name[0] == '\0') {
const char *colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE);
- BLI_strncpy(colorspace_settings->name, colorspace, sizeof(colorspace_settings->name));
+ STRNCPY(colorspace_settings->name, colorspace);
}
if (ibuf != NULL) {
@@ -696,7 +697,7 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char
return NULL;
}
- BLI_strncpy(ibuf->name, name, sizeof(ibuf->name));
+ STRNCPY(ibuf->name, name);
ibuf->userflags |= IB_BITMAPDIRTY;
switch (gen_type) {
@@ -726,7 +727,7 @@ Image *BKE_image_add_generated(
int view_id;
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
- /* BLI_strncpy(ima->name, name, FILE_MAX); */ /* don't do this, this writes in ain invalid filepath! */
+ /* STRNCPY(ima->name, name); */ /* don't do this, this writes in ain invalid filepath! */
ima->gen_x = width;
ima->gen_y = height;
ima->gen_type = gen_type;
@@ -767,7 +768,7 @@ Image *BKE_image_add_from_imbuf(ImBuf *ibuf, const char *name)
ima = image_alloc(G.main, name, IMA_SRC_FILE, IMA_TYPE_IMAGE);
if (ima) {
- BLI_strncpy(ima->name, ibuf->name, FILE_MAX);
+ STRNCPY(ima->name, ibuf->name);
image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
ima->ok = IMA_OK_LOADED;
}
@@ -813,7 +814,7 @@ static void image_memorypack_multiview(Image *ima)
pf->size = ibuf->encodedsize;
imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image PackedFile");
- BLI_strncpy(imapf->filepath, iv->filepath, sizeof(imapf->filepath));
+ STRNCPY(imapf->filepath, iv->filepath);
imapf->packedfile = pf;
BLI_addtail(&ima->packedfiles, imapf);
@@ -863,7 +864,7 @@ void BKE_image_memorypack(Image *ima)
pf->size = ibuf->encodedsize;
imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image PackedFile");
- BLI_strncpy(imapf->filepath, ima->name, sizeof(imapf->filepath));
+ STRNCPY(imapf->filepath, ima->name);
imapf->packedfile = pf;
BLI_addtail(&ima->packedfiles, imapf);
@@ -889,7 +890,7 @@ void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
BLI_addtail(&ima->packedfiles, imapf);
imapf->packedfile = newPackedFile(reports, ima->name, basepath);
if (imapf->packedfile) {
- BLI_strncpy(imapf->filepath, ima->name, sizeof(imapf->filepath));
+ STRNCPY(imapf->filepath, ima->name);
}
else {
BLI_freelinkN(&ima->packedfiles, imapf);
@@ -903,7 +904,7 @@ void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
imapf->packedfile = newPackedFile(reports, iv->filepath, basepath);
if (imapf->packedfile) {
- BLI_strncpy(imapf->filepath, iv->filepath, sizeof(imapf->filepath));
+ STRNCPY(imapf->filepath, iv->filepath);
}
else {
BLI_freelinkN(&ima->packedfiles, imapf);
@@ -923,7 +924,7 @@ void BKE_image_packfiles_from_mem(ReportList *reports, Image *ima, char *data, c
ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), __func__);
BLI_addtail(&ima->packedfiles, imapf);
imapf->packedfile = newPackedFileMemory(data, data_len);
- BLI_strncpy(imapf->filepath, ima->name, sizeof(imapf->filepath));
+ STRNCPY(imapf->filepath, ima->name);
}
}
@@ -1623,6 +1624,7 @@ typedef struct StampData {
char marker[512];
char time[512];
char frame[512];
+ char frame_range[512];
char camera[STAMP_NAME_SIZE];
char cameralens[STAMP_NAME_SIZE];
char scene[STAMP_NAME_SIZE];
@@ -1639,14 +1641,19 @@ typedef struct StampData {
} StampData;
#undef STAMP_NAME_SIZE
-static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int do_prefix)
+/**
+ * \param do_prefix: Include a label like "File ", "Date ", etc. in the stamp data strings.
+ * \param use_dynamic: Also include data that can change on a per-frame basis.
+ */
+static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int do_prefix,
+ bool use_dynamic)
{
char text[256];
struct tm *tl;
time_t t;
if (scene->r.stamp & R_STAMP_FILENAME) {
- BLI_snprintf(stamp_data->file, sizeof(stamp_data->file), do_prefix ? "File %s" : "%s", G.relbase_valid ? G.main->name : "<untitled>");
+ SNPRINTF(stamp_data->file, do_prefix ? "File %s" : "%s", G.relbase_valid ? G.main->name : "<untitled>");
}
else {
stamp_data->file[0] = '\0';
@@ -1654,7 +1661,7 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d
if (scene->r.stamp & R_STAMP_NOTE) {
/* Never do prefix for Note */
- BLI_snprintf(stamp_data->note, sizeof(stamp_data->note), "%s", scene->r.stamp_udata);
+ SNPRINTF(stamp_data->note, "%s", scene->r.stamp_udata);
}
else {
stamp_data->note[0] = '\0';
@@ -1663,83 +1670,93 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d
if (scene->r.stamp & R_STAMP_DATE) {
t = time(NULL);
tl = localtime(&t);
- BLI_snprintf(text, sizeof(text), "%04d/%02d/%02d %02d:%02d:%02d", tl->tm_year + 1900, tl->tm_mon + 1, tl->tm_mday, tl->tm_hour, tl->tm_min, tl->tm_sec);
- BLI_snprintf(stamp_data->date, sizeof(stamp_data->date), do_prefix ? "Date %s" : "%s", text);
+ SNPRINTF(text, "%04d/%02d/%02d %02d:%02d:%02d",
+ tl->tm_year + 1900, tl->tm_mon + 1, tl->tm_mday, tl->tm_hour, tl->tm_min, tl->tm_sec);
+ SNPRINTF(stamp_data->date, do_prefix ? "Date %s" : "%s", text);
}
else {
stamp_data->date[0] = '\0';
}
- if (scene->r.stamp & R_STAMP_MARKER) {
+ if (use_dynamic && scene->r.stamp & R_STAMP_MARKER) {
const char *name = BKE_scene_find_last_marker_name(scene, CFRA);
- if (name) BLI_strncpy(text, name, sizeof(text));
- else BLI_strncpy(text, "<none>", sizeof(text));
+ if (name) STRNCPY(text, name);
+ else STRNCPY(text, "<none>");
- BLI_snprintf(stamp_data->marker, sizeof(stamp_data->marker), do_prefix ? "Marker %s" : "%s", text);
+ SNPRINTF(stamp_data->marker, do_prefix ? "Marker %s" : "%s", text);
}
else {
stamp_data->marker[0] = '\0';
}
- if (scene->r.stamp & R_STAMP_TIME) {
+ if (use_dynamic && scene->r.stamp & R_STAMP_TIME) {
const short timecode_style = USER_TIMECODE_SMPTE_FULL;
BLI_timecode_string_from_time(text, sizeof(text), 0, FRA2TIME(scene->r.cfra), FPS, timecode_style);
- BLI_snprintf(stamp_data->time, sizeof(stamp_data->time), do_prefix ? "Timecode %s" : "%s", text);
+ SNPRINTF(stamp_data->time, do_prefix ? "Timecode %s" : "%s", text);
}
else {
stamp_data->time[0] = '\0';
}
- if (scene->r.stamp & R_STAMP_FRAME) {
+ if (use_dynamic && scene->r.stamp & R_STAMP_FRAME) {
char fmtstr[32];
int digits = 1;
if (scene->r.efra > 9)
digits = integer_digits_i(scene->r.efra);
- BLI_snprintf(fmtstr, sizeof(fmtstr), do_prefix ? "Frame %%0%di" : "%%0%di", digits);
- BLI_snprintf(stamp_data->frame, sizeof(stamp_data->frame), fmtstr, scene->r.cfra);
+ SNPRINTF(fmtstr, do_prefix ? "Frame %%0%di" : "%%0%di", digits);
+ SNPRINTF(stamp_data->frame, fmtstr, scene->r.cfra);
}
else {
stamp_data->frame[0] = '\0';
}
- if (scene->r.stamp & R_STAMP_CAMERA) {
- BLI_snprintf(stamp_data->camera, sizeof(stamp_data->camera), do_prefix ? "Camera %s" : "%s", camera ? camera->id.name + 2 : "<none>");
+ if (scene->r.stamp & R_STAMP_FRAME_RANGE) {
+ SNPRINTF(stamp_data->frame_range,
+ do_prefix ? "Frame Range %d:%d" : "%d:%d",
+ scene->r.sfra, scene->r.efra);
+ }
+ else {
+ stamp_data->frame_range[0] = '\0';
+ }
+
+ if (use_dynamic && scene->r.stamp & R_STAMP_CAMERA) {
+ SNPRINTF(stamp_data->camera, do_prefix ? "Camera %s" : "%s", camera ? camera->id.name + 2 : "<none>");
}
else {
stamp_data->camera[0] = '\0';
}
- if (scene->r.stamp & R_STAMP_CAMERALENS) {
+ if (use_dynamic && scene->r.stamp & R_STAMP_CAMERALENS) {
if (camera && camera->type == OB_CAMERA) {
- BLI_snprintf(text, sizeof(text), "%.2f", ((Camera *)camera->data)->lens);
+ SNPRINTF(text, "%.2f", ((Camera *)camera->data)->lens);
}
else {
- BLI_strncpy(text, "<none>", sizeof(text));
+ STRNCPY(text, "<none>");
}
- BLI_snprintf(stamp_data->cameralens, sizeof(stamp_data->cameralens), do_prefix ? "Lens %s" : "%s", text);
+ SNPRINTF(stamp_data->cameralens, do_prefix ? "Lens %s" : "%s", text);
}
else {
stamp_data->cameralens[0] = '\0';
}
if (scene->r.stamp & R_STAMP_SCENE) {
- BLI_snprintf(stamp_data->scene, sizeof(stamp_data->scene), do_prefix ? "Scene %s" : "%s", scene->id.name + 2);
+ SNPRINTF(stamp_data->scene, do_prefix ? "Scene %s" : "%s", scene->id.name + 2);
}
else {
stamp_data->scene[0] = '\0';
}
- if (scene->r.stamp & R_STAMP_SEQSTRIP) {
+ if (use_dynamic && scene->r.stamp & R_STAMP_SEQSTRIP) {
Sequence *seq = BKE_sequencer_foreground_frame_get(scene, scene->r.cfra);
- if (seq) BLI_strncpy(text, seq->name + 2, sizeof(text));
- else BLI_strncpy(text, "<none>", sizeof(text));
+ if (seq) STRNCPY(text, seq->name + 2);
+ else STRNCPY(text, "<none>");
- BLI_snprintf(stamp_data->strip, sizeof(stamp_data->strip), do_prefix ? "Strip %s" : "%s", text);
+ SNPRINTF(stamp_data->strip, do_prefix ? "Strip %s" : "%s", text);
}
else {
stamp_data->strip[0] = '\0';
@@ -1749,22 +1766,29 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d
Render *re = RE_GetSceneRender(scene);
RenderStats *stats = re ? RE_GetStats(re) : NULL;
- if (stats && (scene->r.stamp & R_STAMP_RENDERTIME)) {
+ if (use_dynamic && stats && (scene->r.stamp & R_STAMP_RENDERTIME)) {
BLI_timecode_string_from_time_simple(text, sizeof(text), stats->lastframetime);
- BLI_snprintf(stamp_data->rendertime, sizeof(stamp_data->rendertime), do_prefix ? "RenderTime %s" : "%s", text);
+ SNPRINTF(stamp_data->rendertime, do_prefix ? "RenderTime %s" : "%s", text);
}
else {
stamp_data->rendertime[0] = '\0';
}
- if (stats && (scene->r.stamp & R_STAMP_MEMORY)) {
- BLI_snprintf(stamp_data->memory, sizeof(stamp_data->memory), do_prefix ? "Peak Memory %.2fM" : "%.2fM", stats->mem_peak);
+ if (use_dynamic && stats && (scene->r.stamp & R_STAMP_MEMORY)) {
+ SNPRINTF(stamp_data->memory, do_prefix ? "Peak Memory %.2fM" : "%.2fM", stats->mem_peak);
}
else {
stamp_data->memory[0] = '\0';
}
}
+ if (scene->r.stamp & R_STAMP_FRAME_RANGE) {
+ SNPRINTF(stamp_data->frame_range,
+ do_prefix ? "Frame Range %d:%d" : "%d:%d", scene->r.sfra, scene->r.efra);
+ }
+ else {
+ stamp_data->frame_range[0] = '\0';
+ }
}
/* Will always add prefix. */
@@ -1773,73 +1797,73 @@ static void stampdata_from_template(StampData *stamp_data,
const StampData *stamp_data_template)
{
if (scene->r.stamp & R_STAMP_FILENAME) {
- BLI_snprintf(stamp_data->file, sizeof(stamp_data->file), "File %s", stamp_data_template->file);
+ SNPRINTF(stamp_data->file, "File %s", stamp_data_template->file);
}
else {
stamp_data->file[0] = '\0';
}
if (scene->r.stamp & R_STAMP_NOTE) {
- BLI_snprintf(stamp_data->note, sizeof(stamp_data->note), "%s", stamp_data_template->note);
+ SNPRINTF(stamp_data->note, "%s", stamp_data_template->note);
}
else {
stamp_data->note[0] = '\0';
}
if (scene->r.stamp & R_STAMP_DATE) {
- BLI_snprintf(stamp_data->date, sizeof(stamp_data->date), "Date %s", stamp_data_template->date);
+ SNPRINTF(stamp_data->date, "Date %s", stamp_data_template->date);
}
else {
stamp_data->date[0] = '\0';
}
if (scene->r.stamp & R_STAMP_MARKER) {
- BLI_snprintf(stamp_data->marker, sizeof(stamp_data->marker), "Marker %s", stamp_data_template->marker);
+ SNPRINTF(stamp_data->marker, "Marker %s", stamp_data_template->marker);
}
else {
stamp_data->marker[0] = '\0';
}
if (scene->r.stamp & R_STAMP_TIME) {
- BLI_snprintf(stamp_data->time, sizeof(stamp_data->time), "Timecode %s", stamp_data_template->time);
+ SNPRINTF(stamp_data->time, "Timecode %s", stamp_data_template->time);
}
else {
stamp_data->time[0] = '\0';
}
if (scene->r.stamp & R_STAMP_FRAME) {
- BLI_snprintf(stamp_data->frame, sizeof(stamp_data->frame), "Frame %s", stamp_data_template->frame);
+ SNPRINTF(stamp_data->frame, "Frame %s", stamp_data_template->frame);
}
else {
stamp_data->frame[0] = '\0';
}
if (scene->r.stamp & R_STAMP_CAMERA) {
- BLI_snprintf(stamp_data->camera, sizeof(stamp_data->camera), "Camera %s", stamp_data_template->camera);
+ SNPRINTF(stamp_data->camera, "Camera %s", stamp_data_template->camera);
}
else {
stamp_data->camera[0] = '\0';
}
if (scene->r.stamp & R_STAMP_CAMERALENS) {
- BLI_snprintf(stamp_data->cameralens, sizeof(stamp_data->cameralens), "Lens %s", stamp_data_template->cameralens);
+ SNPRINTF(stamp_data->cameralens, "Lens %s", stamp_data_template->cameralens);
}
else {
stamp_data->cameralens[0] = '\0';
}
if (scene->r.stamp & R_STAMP_SCENE) {
- BLI_snprintf(stamp_data->scene, sizeof(stamp_data->scene), "Scene %s", stamp_data_template->scene);
+ SNPRINTF(stamp_data->scene, "Scene %s", stamp_data_template->scene);
}
else {
stamp_data->scene[0] = '\0';
}
if (scene->r.stamp & R_STAMP_SEQSTRIP) {
- BLI_snprintf(stamp_data->strip, sizeof(stamp_data->strip), "Strip %s", stamp_data_template->strip);
+ SNPRINTF(stamp_data->strip, "Strip %s", stamp_data_template->strip);
}
else {
stamp_data->strip[0] = '\0';
}
if (scene->r.stamp & R_STAMP_RENDERTIME) {
- BLI_snprintf(stamp_data->rendertime, sizeof(stamp_data->rendertime), "RenderTime %s", stamp_data_template->rendertime);
+ SNPRINTF(stamp_data->rendertime, "RenderTime %s", stamp_data_template->rendertime);
}
else {
stamp_data->rendertime[0] = '\0';
}
if (scene->r.stamp & R_STAMP_MEMORY) {
- BLI_snprintf(stamp_data->memory, sizeof(stamp_data->memory), "Peak Memory %s", stamp_data_template->memory);
+ SNPRINTF(stamp_data->memory, "Peak Memory %s", stamp_data_template->memory);
}
else {
stamp_data->memory[0] = '\0';
@@ -1885,7 +1909,7 @@ void BKE_image_stamp_buf(
display = IMB_colormanagement_display_get_named(display_device);
if (stamp_data_template == NULL) {
- stampdata(scene, camera, &stamp_data, (scene->r.stamp & R_STAMP_HIDE_LABELS) == 0);
+ stampdata(scene, camera, &stamp_data, (scene->r.stamp & R_STAMP_HIDE_LABELS) == 0, true);
}
else {
stampdata_from_template(&stamp_data, scene, stamp_data_template);
@@ -2106,13 +2130,28 @@ void BKE_render_result_stamp_info(Scene *scene, Object *camera, struct RenderRes
}
if (!allocate_only)
- stampdata(scene, camera, stamp_data, 0);
+ stampdata(scene, camera, stamp_data, 0, true);
if (!rr->stamp_data) {
rr->stamp_data = stamp_data;
}
}
+struct StampData *BKE_stamp_info_from_scene_static(Scene *scene)
+{
+ struct StampData *stamp_data;
+
+ if (!(scene && (scene->r.stamp & R_STAMP_ALL)))
+ return NULL;
+
+ /* Memory is allocated here (instead of by the caller) so that the caller
+ * doesn't have to know the size of the StampData struct. */
+ stamp_data = MEM_callocN(sizeof(StampData), __func__);
+ stampdata(scene, NULL, stamp_data, 0, false);
+
+ return stamp_data;
+}
+
void BKE_stamp_info_callback(void *data, struct StampData *stamp_data, StampCallback callback, bool noskip)
{
if ((callback == NULL) || (stamp_data == NULL)) {
@@ -2130,6 +2169,7 @@ void BKE_stamp_info_callback(void *data, struct StampData *stamp_data, StampCall
CALL(marker, "Marker");
CALL(time, "Time");
CALL(frame, "Frame");
+ CALL(frame_range, "FrameRange");
CALL(camera, "Camera");
CALL(cameralens, "Lens");
CALL(scene, "Scene");
@@ -2158,8 +2198,8 @@ void BKE_render_result_stamp_data(RenderResult *rr, const char *key, const char
stamp_data = rr->stamp_data;
StampDataCustomField *field = MEM_mallocN(sizeof(StampDataCustomField),
"StampData Custom Field");
- BLI_strncpy(field->key, key, sizeof(field->key));
- BLI_strncpy(field->value, value, sizeof(field->value));
+ STRNCPY(field->key, key);
+ STRNCPY(field->value, value);
BLI_addtail(&stamp_data->custom_fields, field);
}
@@ -2173,27 +2213,31 @@ void BKE_stamp_data_free(struct StampData *stamp_data)
}
/* wrap for callback only */
-static void metadata_change_field(void *data, const char *propname, char *propvalue, int UNUSED(len))
+static void metadata_set_field(void *data, const char *propname, char *propvalue, int UNUSED(len))
{
- IMB_metadata_change_field(data, propname, propvalue);
+ /* We know it is an ImBuf* because that's what we pass to BKE_stamp_info_callback. */
+ struct ImBuf *imbuf = data;
+ IMB_metadata_set_field(imbuf->metadata, propname, propvalue);
}
static void metadata_get_field(void *data, const char *propname, char *propvalue, int len)
{
- IMB_metadata_get_field(data, propname, propvalue, len);
+ /* We know it is an ImBuf* because that's what we pass to BKE_stamp_info_callback. */
+ struct ImBuf *imbuf = data;
+ IMB_metadata_get_field(imbuf->metadata, propname, propvalue, len);
}
void BKE_imbuf_stamp_info(RenderResult *rr, struct ImBuf *ibuf)
{
struct StampData *stamp_data = rr->stamp_data;
-
- BKE_stamp_info_callback(ibuf, stamp_data, metadata_change_field, false);
+ IMB_metadata_ensure(&ibuf->metadata);
+ BKE_stamp_info_callback(ibuf, stamp_data, metadata_set_field, false);
}
void BKE_stamp_info_from_imbuf(RenderResult *rr, struct ImBuf *ibuf)
{
struct StampData *stamp_data = rr->stamp_data;
-
+ IMB_metadata_ensure(&ibuf->metadata);
BKE_stamp_info_callback(ibuf, stamp_data, metadata_get_field, true);
}
@@ -2548,7 +2592,7 @@ void BKE_image_verify_viewer_views(const RenderData *rd, Image *ima, ImageUser *
bool do_reset;
const bool is_multiview = (rd->scemode & R_MULTIVIEW) != 0;
- BLI_lock_thread(LOCK_DRAW_IMAGE);
+ BLI_thread_lock(LOCK_DRAW_IMAGE);
if (!BKE_scene_multiview_is_stereo3d(rd))
iuser->flag &= ~IMA_SHOW_STEREO;
@@ -2582,7 +2626,7 @@ void BKE_image_verify_viewer_views(const RenderData *rd, Image *ima, ImageUser *
BLI_spin_unlock(&image_spin);
}
- BLI_unlock_thread(LOCK_DRAW_IMAGE);
+ BLI_thread_unlock(LOCK_DRAW_IMAGE);
}
void BKE_image_walk_all_users(const Main *mainp, void *customdata,
@@ -2740,7 +2784,7 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
if (BKE_image_has_packedfile(ima)) {
const int totfiles = image_num_files(ima);
- if (totfiles != BLI_listbase_count_ex(&ima->packedfiles, totfiles + 1)) {
+ if (totfiles != BLI_listbase_count_at_most(&ima->packedfiles, totfiles + 1)) {
/* in case there are new available files to be loaded */
image_free_packedfiles(ima);
BKE_image_packfiles(NULL, ima, ID_BLEND_PATH(G.main, &ima->id));
@@ -2895,7 +2939,7 @@ void BKE_image_multiview_index(Image *ima, ImageUser *iuser)
iuser->multi_index = iuser->multiview_eye;
}
else {
- if ((iuser->view < 0) || (iuser->view >= BLI_listbase_count_ex(&ima->views, iuser->view + 1))) {
+ if ((iuser->view < 0) || (iuser->view >= BLI_listbase_count_at_most(&ima->views, iuser->view + 1))) {
iuser->multi_index = iuser->view = 0;
}
else {
@@ -2958,7 +3002,7 @@ static void image_init_multilayer_multiview(Image *ima, RenderResult *rr)
if (rr) {
for (RenderView *rv = rr->views.first; rv; rv = rv->next) {
ImageView *iv = MEM_callocN(sizeof(ImageView), "Viewer Image View");
- BLI_strncpy(iv->name, rv->name, sizeof(iv->name));
+ STRNCPY(iv->name, rv->name);
BLI_addtail(&ima->views, iv);
}
}
@@ -3039,8 +3083,8 @@ static void image_add_view(Image *ima, const char *viewname, const char *filepat
ImageView *iv;
iv = MEM_mallocN(sizeof(ImageView), "Viewer Image View");
- BLI_strncpy(iv->name, viewname, sizeof(iv->name));
- BLI_strncpy(iv->filepath, filepath, sizeof(iv->filepath));
+ STRNCPY(iv->name, viewname);
+ STRNCPY(iv->filepath, filepath);
/* For stereo drawing we need to ensure:
* STEREO_LEFT_NAME == STEREO_LEFT_ID and
@@ -3362,7 +3406,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
const int totfiles = image_num_files(ima);
int i;
- if (totfiles != BLI_listbase_count_ex(&ima->anims, totfiles + 1)) {
+ if (totfiles != BLI_listbase_count_at_most(&ima->anims, totfiles + 1)) {
image_free_anims(ima);
for (i = 0; i < totfiles; i++) {
@@ -3490,7 +3534,7 @@ static ImBuf *load_image_single(
ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image Packefile");
BLI_addtail(&ima->packedfiles, imapf);
- BLI_strncpy(imapf->filepath, filepath, sizeof(imapf->filepath));
+ STRNCPY(imapf->filepath, filepath);
imapf->packedfile = newPackedFile(NULL, filepath, ID_BLEND_PATH(G.main, &ima->id));
}
}
@@ -3518,7 +3562,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
/* this should never happen, but just playing safe */
if (has_packed) {
- if (totfiles != BLI_listbase_count_ex(&ima->packedfiles, totfiles + 1)) {
+ if (totfiles != BLI_listbase_count_at_most(&ima->packedfiles, totfiles + 1)) {
image_free_packedfiles(ima);
has_packed = false;
}
@@ -3663,7 +3707,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
/* release is done in BKE_image_release_ibuf using r_lock */
if (from_render) {
- BLI_lock_thread(LOCK_VIEWER);
+ BLI_thread_lock(LOCK_VIEWER);
*r_lock = re;
rv = NULL;
}
@@ -3756,7 +3800,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
}
/* invalidate color managed buffers if render result changed */
- BLI_lock_thread(LOCK_COLORMANAGE);
+ BLI_thread_lock(LOCK_COLORMANAGE);
if (ibuf->x != rres.rectx || ibuf->y != rres.recty || ibuf->rect_float != rectf) {
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
}
@@ -3797,7 +3841,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
ibuf->flags &= ~IB_zbuffloat;
}
- BLI_unlock_thread(LOCK_COLORMANAGE);
+ BLI_thread_unlock(LOCK_COLORMANAGE);
ibuf->dither = dither;
@@ -3999,7 +4043,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
/* requires lock/unlock, otherwise don't return image */
if (r_lock) {
/* unlock in BKE_image_release_ibuf */
- BLI_lock_thread(LOCK_VIEWER);
+ BLI_thread_lock(LOCK_VIEWER);
*r_lock = ima;
/* XXX anim play for viewer nodes not yet supported */
@@ -4052,11 +4096,11 @@ void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
if (lock) {
/* for getting image during threaded render / compositing, need to release */
if (lock == ima) {
- BLI_unlock_thread(LOCK_VIEWER); /* viewer image */
+ BLI_thread_unlock(LOCK_VIEWER); /* viewer image */
}
else if (lock) {
RE_ReleaseResultImage(lock); /* render result */
- BLI_unlock_thread(LOCK_VIEWER); /* view image imbuf */
+ BLI_thread_unlock(LOCK_VIEWER); /* view image imbuf */
}
}
@@ -4645,7 +4689,7 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
for (srv = scene->r.views.first; srv; srv = srv->next) {
if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) {
char filepath[FILE_MAX];
- BLI_snprintf(filepath, sizeof(filepath), "%s%s%s", prefix, srv->suffix, ext);
+ SNPRINTF(filepath, "%s%s%s", prefix, srv->suffix, ext);
image_add_view(ima, srv->name, filepath);
}
}
@@ -4656,7 +4700,7 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
int file;
char str[FILE_MAX];
- BLI_strncpy(str, iv->filepath, sizeof(str));
+ STRNCPY(str, iv->filepath);
BLI_path_abs(str, G.main->name);
/* exists? */
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 00cf40f06cd..fcbc25ebad5 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -1663,7 +1663,7 @@ static void nlastrips_to_animdata(ID *id, ListBase *strips)
/* trying to add to the current failed (no space),
* so add a new track to the stack, and add to that...
*/
- nlt = add_nlatrack(adt, NULL);
+ nlt = BKE_nlatrack_add(adt, NULL);
BKE_nlatrack_add_strip(nlt, strip);
}
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index 931fc09d235..bf36c437d60 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -47,7 +47,6 @@
#include "BKE_animsys.h"
#include "BKE_colortools.h"
#include "BKE_icons.h"
-#include "BKE_global.h"
#include "BKE_lamp.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index d92d0d9edbf..c41ad78977e 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -54,7 +54,6 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
-#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index c6515d0c47a..50c7dc0c02f 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -57,10 +57,9 @@
#include "MEM_guardedalloc.h"
-#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-
/* prototype */
struct EngineSettingsCB_Type;
+static void layer_collections_sync_flags(ListBase *layer_collections_dst, const ListBase *layer_collections_src);
static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc);
static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollection *lc, ListBase *objects);
static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollection *parent, SceneCollection *sc);
@@ -217,6 +216,8 @@ void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user)
MEM_freeN(view_layer->id_properties);
}
+ MEM_SAFE_FREE(view_layer->object_bases_array);
+
MEM_freeN(view_layer);
}
@@ -353,27 +354,95 @@ static SceneCollection *scene_collection_from_new_tree(
return NULL;
}
+static void layer_collection_sync_flags(
+ LayerCollection *layer_collection_dst,
+ const LayerCollection *layer_collection_src)
+{
+ layer_collection_dst->flag = layer_collection_src->flag;
+
+ if (layer_collection_dst->properties != NULL) {
+ IDP_FreeProperty(layer_collection_dst->properties);
+ MEM_SAFE_FREE(layer_collection_dst->properties);
+ }
+
+ if (layer_collection_src->properties != NULL) {
+ layer_collection_dst->properties = IDP_CopyProperty(layer_collection_src->properties);
+ }
+
+ layer_collections_sync_flags(&layer_collection_dst->layer_collections,
+ &layer_collection_src->layer_collections);
+}
+
static void layer_collections_sync_flags(ListBase *layer_collections_dst, const ListBase *layer_collections_src)
{
+ BLI_assert(BLI_listbase_count(layer_collections_dst) == BLI_listbase_count(layer_collections_src));
LayerCollection *layer_collection_dst = (LayerCollection *)layer_collections_dst->first;
const LayerCollection *layer_collection_src = (const LayerCollection *)layer_collections_src->first;
while (layer_collection_dst != NULL) {
- layer_collection_dst->flag = layer_collection_src->flag;
+ layer_collection_sync_flags(layer_collection_dst, layer_collection_src);
+ layer_collection_dst = layer_collection_dst->next;
+ layer_collection_src = layer_collection_src->next;
+ }
+}
- if (layer_collection_dst->properties != NULL) {
- IDP_FreeProperty(layer_collection_dst->properties);
- MEM_SAFE_FREE(layer_collection_dst->properties);
+static bool layer_collection_sync_if_match(
+ ListBase *lb,
+ const SceneCollection *scene_collection_dst,
+ const SceneCollection *scene_collection_src)
+{
+ for (LayerCollection *layer_collection = lb->first;
+ layer_collection;
+ layer_collection = layer_collection->next)
+ {
+ if (layer_collection->scene_collection == scene_collection_src) {
+ LayerCollection *layer_collection_dst =
+ BLI_findptr(
+ lb,
+ scene_collection_dst,
+ offsetof(LayerCollection, scene_collection));
+
+ if (layer_collection_dst != NULL) {
+ layer_collection_sync_flags(layer_collection_dst, layer_collection);
+ }
+ return true;
}
-
- if (layer_collection_src->properties != NULL) {
- layer_collection_dst->properties = IDP_CopyProperty(layer_collection_src->properties);
+ else {
+ if (layer_collection_sync_if_match(
+ &layer_collection->layer_collections,
+ scene_collection_dst,
+ scene_collection_src))
+ {
+ return true;
+ }
}
+ }
+ return false;
+}
- layer_collections_sync_flags(&layer_collection_dst->layer_collections,
- &layer_collection_src->layer_collections);
-
- layer_collection_dst = layer_collection_dst->next;
- layer_collection_src = layer_collection_src->next;
+/**
+ * Sync sibling collections across all view layers
+ *
+ * Make sure every linked instance of \a scene_collection_dst has the same values
+ * (flags, overrides, ...) as the corresponding scene_collection_src.
+ *
+ * \note expect scene_collection_dst to be scene_collection_src->next, and it also
+ * expects both collections to have the same ammount of sub-collections.
+ */
+void BKE_layer_collection_sync_flags(
+ ID *owner_id,
+ SceneCollection *scene_collection_dst,
+ SceneCollection *scene_collection_src)
+{
+ for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
+ for (LayerCollection *layer_collection = view_layer->layer_collections.first;
+ layer_collection;
+ layer_collection = layer_collection->next)
+ {
+ layer_collection_sync_if_match(
+ &layer_collection->layer_collections,
+ scene_collection_dst,
+ scene_collection_src);
+ }
}
}
@@ -436,6 +505,80 @@ void BKE_view_layer_copy_data(
view_layer_dst->basact = base_dst;
}
}
+
+ view_layer_dst->object_bases_array = NULL;
+}
+
+/**
+ * Find and return the ListBase of LayerCollection that has \a lc_child as one of its directly
+ * nested LayerCollection.
+ *
+ * \param lb_parent Initial ListBase of LayerCollection to look into recursively
+ * usually the view layer's collection list
+ */
+static ListBase *find_layer_collection_parent_list_base(ListBase *lb_parent, const LayerCollection *lc_child)
+{
+ for (LayerCollection *lc_nested = lb_parent->first; lc_nested; lc_nested = lc_nested->next) {
+ if (lc_nested == lc_child) {
+ return lb_parent;
+ }
+
+ ListBase *found = find_layer_collection_parent_list_base(&lc_nested->layer_collections, lc_child);
+ if (found != NULL) {
+ return found;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Makes a shallow copy of a LayerCollection
+ *
+ * Add a new collection in the same level as the old one (linking if necessary),
+ * and copy all the collection data across them.
+ */
+struct LayerCollection *BKE_layer_collection_duplicate(struct ID *owner_id, struct LayerCollection *layer_collection)
+{
+ SceneCollection *scene_collection, *scene_collection_new;
+
+ scene_collection = layer_collection->scene_collection;
+ scene_collection_new = BKE_collection_duplicate(owner_id, scene_collection);
+
+ LayerCollection *layer_collection_new = NULL;
+
+ /* If the original layer_collection was directly linked to the view layer
+ we need to link the new scene collection here as well. */
+ for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
+ if (BLI_findindex(&view_layer->layer_collections, layer_collection) != -1) {
+ layer_collection_new = BKE_collection_link(view_layer, scene_collection_new);
+ layer_collection_sync_flags(layer_collection_new, layer_collection);
+
+ if (layer_collection_new != layer_collection->next) {
+ BLI_remlink(&view_layer->layer_collections, layer_collection_new);
+ BLI_insertlinkafter(&view_layer->layer_collections, layer_collection, layer_collection_new);
+ }
+ break;
+ }
+ }
+
+ /* Otherwise just try to find the corresponding layer collection to return it back. */
+ if (layer_collection_new == NULL) {
+ for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
+ ListBase *layer_collections_parent;
+ layer_collections_parent = find_layer_collection_parent_list_base(
+ &view_layer->layer_collections,
+ layer_collection);
+ if (layer_collections_parent != NULL) {
+ layer_collection_new = BLI_findptr(
+ layer_collections_parent,
+ scene_collection_new,
+ offsetof(LayerCollection, scene_collection));
+ break;
+ }
+ }
+ }
+ return layer_collection_new;
}
static void view_layer_object_base_unref(ViewLayer *view_layer, Base *base)
@@ -988,6 +1131,34 @@ void BKE_layer_collection_resync(const ID *owner_id, const SceneCollection *sc)
/* ---------------------------------------------------------------------- */
/**
+ * Select all the objects of this layer collection
+ *
+ * It also select the objects that are in nested collections.
+ * \note Recursive
+ */
+void BKE_layer_collection_objects_select(struct LayerCollection *layer_collection)
+{
+ if ((layer_collection->flag & COLLECTION_DISABLED) ||
+ ((layer_collection->flag & COLLECTION_SELECTABLE) == 0))
+ {
+ return;
+ }
+
+ for (LinkData *link = layer_collection->object_bases.first; link; link = link->next) {
+ Base *base = link->data;
+ if (base->flag & BASE_SELECTABLED) {
+ base->flag |= BASE_SELECTED;
+ }
+ }
+
+ for (LayerCollection *iter = layer_collection->layer_collections.first; iter; iter = iter->next) {
+ BKE_layer_collection_objects_select(iter);
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+/**
* Link a collection to a renderlayer
* The collection needs to be created separately
*/
@@ -1115,16 +1286,29 @@ static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollect
/* ---------------------------------------------------------------------- */
/**
- * See if render layer has the scene collection linked directly, or indirectly (nested)
+ * Return the first matching LayerCollection in the ViewLayer for the SceneCollection.
*/
-bool BKE_view_layer_has_collection(ViewLayer *view_layer, const SceneCollection *sc)
+LayerCollection *BKE_layer_collection_first_from_scene_collection(ViewLayer *view_layer, const SceneCollection *scene_collection)
{
- for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
- if (find_layer_collection_by_scene_collection(lc, sc) != NULL) {
- return true;
+ for (LayerCollection *layer_collection = view_layer->layer_collections.first;
+ layer_collection != NULL;
+ layer_collection = layer_collection->next)
+ {
+ LayerCollection *found = find_layer_collection_by_scene_collection(layer_collection, scene_collection);
+
+ if (found != NULL) {
+ return found;
}
}
- return false;
+ return NULL;
+}
+
+/**
+ * See if view layer has the scene collection linked directly, or indirectly (nested)
+ */
+bool BKE_view_layer_has_collection(ViewLayer *view_layer, const SceneCollection *scene_collection)
+{
+ return BKE_layer_collection_first_from_scene_collection(view_layer, scene_collection) != NULL;
}
/**
@@ -1968,12 +2152,13 @@ void BKE_visible_bases_iterator_end(BLI_Iterator *UNUSED(iter))
void BKE_renderable_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
{
- ObjectsRenderableIteratorData *data = data_in;
+ struct ObjectsRenderableIteratorData *data = data_in;
+ /* Tag objects to prevent going over the same object twice. */
for (Scene *scene = data->scene; scene; scene = scene->set) {
for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- base->object->id.flag |= LIB_TAG_DOIT;
+ base->object->id.flag |= LIB_TAG_DOIT;
}
}
}
@@ -1981,8 +2166,8 @@ void BKE_renderable_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
ViewLayer *view_layer = data->scene->view_layers.first;
data->iter.view_layer = view_layer;
- Base base = {(Base *)view_layer->object_bases.first, NULL};
- data->iter.base = &base;
+ data->base_temp.next = view_layer->object_bases.first;
+ data->iter.base = &data->base_temp;
data->iter.set = NULL;
@@ -1992,18 +2177,27 @@ void BKE_renderable_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
void BKE_renderable_objects_iterator_next(BLI_Iterator *iter)
{
- ObjectsRenderableIteratorData *data = iter->data;
+ /* Set it early in case we need to exit and we are running from within a loop. */
+ iter->skip = true;
+
+ struct ObjectsRenderableIteratorData *data = iter->data;
Base *base = data->iter.base->next;
/* There is still a base in the current scene layer. */
if (base != NULL) {
Object *ob = base->object;
- iter->current = ob;
+ /* We need to set the iter.base even if the rest fail otherwise
+ * we keep checking the exactly same base over and over again. */
data->iter.base = base;
- if ((base->flag & BASE_VISIBLED) == 0) {
- BKE_renderable_objects_iterator_next(iter);
+ if (ob->id.flag & LIB_TAG_DOIT) {
+ ob->id.flag &= ~LIB_TAG_DOIT;
+
+ if ((base->flag & BASE_VISIBLED) != 0) {
+ iter->skip = false;
+ iter->current = ob;
+ }
}
return;
}
@@ -2013,30 +2207,23 @@ void BKE_renderable_objects_iterator_next(BLI_Iterator *iter)
while ((data->iter.view_layer = data->iter.view_layer->next)) {
ViewLayer *view_layer = data->iter.view_layer;
if (view_layer->flag & VIEW_LAYER_RENDER) {
-
- Base base_iter = {(Base *)view_layer->object_bases.first, NULL};
- data->iter.base = &base_iter;
-
- BKE_renderable_objects_iterator_next(iter);
+ data->base_temp.next = view_layer->object_bases.first;
+ data->iter.base = &data->base_temp;
return;
}
}
/* Setup the "set" for the next iteration. */
- Scene scene = {.set = data->scene};
- data->iter.set = &scene;
- BKE_renderable_objects_iterator_next(iter);
+ data->scene_temp.set = data->scene;
+ data->iter.set = &data->scene_temp;
return;
}
/* Look for an object in the next set. */
while ((data->iter.set = data->iter.set->set)) {
ViewLayer *view_layer = BKE_view_layer_from_scene_get(data->iter.set);
-
- Base base_iter = {(Base *)view_layer->object_bases.first, NULL};
- data->iter.base = &base_iter;
-
- BKE_renderable_objects_iterator_next(iter);
+ data->base_temp.next = view_layer->object_bases.first;
+ data->iter.base = &data->base_temp;
return;
}
@@ -2070,10 +2257,9 @@ static void idproperty_reset(IDProperty **props, IDProperty *props_ref)
}
}
-void BKE_layer_eval_layer_collection_pre(const struct EvaluationContext *UNUSED(eval_ctx),
- ID *owner_id, ViewLayer *view_layer)
+static void layer_eval_layer_collection_pre(ID *owner_id, ViewLayer *view_layer)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, view_layer->name, view_layer);
+ DEG_debug_print_eval(__func__, view_layer->name, view_layer);
Scene *scene = (GS(owner_id->name) == ID_SCE) ? (Scene *)owner_id : NULL;
for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
@@ -2113,18 +2299,21 @@ static bool layer_collection_visible_get(const EvaluationContext *eval_ctx, Laye
}
}
-void BKE_layer_eval_layer_collection(const EvaluationContext *eval_ctx,
- LayerCollection *layer_collection,
- LayerCollection *parent_layer_collection)
+static void layer_eval_layer_collection(const EvaluationContext *eval_ctx,
+ LayerCollection *layer_collection,
+ LayerCollection *parent_layer_collection)
{
- DEBUG_PRINT("%s on %s (%p) [%s], parent %s (%p) [%s]\n",
- __func__,
- layer_collection->scene_collection->name,
- layer_collection->scene_collection,
- collection_type_lookup[layer_collection->scene_collection->type],
- (parent_layer_collection != NULL) ? parent_layer_collection->scene_collection->name : "NONE",
- (parent_layer_collection != NULL) ? parent_layer_collection->scene_collection : NULL,
- (parent_layer_collection != NULL) ? collection_type_lookup[parent_layer_collection->scene_collection->type] : "");
+ if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) {
+ /* TODO)sergey): Try to make it more generic and handled by depsgraph messaging. */
+ printf("%s on %s (%p) [%s], parent %s (%p) [%s]\n",
+ __func__,
+ layer_collection->scene_collection->name,
+ layer_collection->scene_collection,
+ collection_type_lookup[layer_collection->scene_collection->type],
+ (parent_layer_collection != NULL) ? parent_layer_collection->scene_collection->name : "NONE",
+ (parent_layer_collection != NULL) ? parent_layer_collection->scene_collection : NULL,
+ (parent_layer_collection != NULL) ? collection_type_lookup[parent_layer_collection->scene_collection->type] : "");
+ }
BLI_assert(layer_collection != parent_layer_collection);
/* visibility */
@@ -2170,18 +2359,65 @@ void BKE_layer_eval_layer_collection(const EvaluationContext *eval_ctx,
}
}
-void BKE_layer_eval_layer_collection_post(const struct EvaluationContext *UNUSED(eval_ctx),
- ViewLayer *view_layer)
+static void layer_eval_layer_collection_post(ViewLayer *view_layer)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, view_layer->name, view_layer);
- /* if base is not selectabled, clear select */
+ DEG_debug_print_eval(__func__, view_layer->name, view_layer);
+ /* Create array of bases, for fast index-based lookup. */
+ const int num_object_bases = BLI_listbase_count(&view_layer->object_bases);
+ MEM_SAFE_FREE(view_layer->object_bases_array);
+ view_layer->object_bases_array = MEM_malloc_arrayN(
+ num_object_bases, sizeof(Base *), "view_layer->object_bases_array");
+ int base_index = 0;
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ /* if base is not selectabled, clear select. */
if ((base->flag & BASE_SELECTABLED) == 0) {
base->flag &= ~BASE_SELECTED;
}
+ /* Store base in the array. */
+ view_layer->object_bases_array[base_index++] = base;
+ }
+}
+
+static void layer_eval_collections_recurse(const EvaluationContext *eval_ctx,
+ ListBase *layer_collections,
+ LayerCollection *parent_layer_collection)
+{
+ for (LayerCollection *layer_collection = layer_collections->first;
+ layer_collection != NULL;
+ layer_collection = layer_collection->next)
+ {
+ layer_eval_layer_collection(eval_ctx,
+ layer_collection,
+ parent_layer_collection);
+ layer_eval_collections_recurse(eval_ctx,
+ &layer_collection->layer_collections,
+ layer_collection);
}
}
+void BKE_layer_eval_view_layer(const struct EvaluationContext *eval_ctx,
+ struct ID *owner_id,
+ ViewLayer *view_layer)
+{
+ layer_eval_layer_collection_pre(owner_id, view_layer);
+ layer_eval_collections_recurse(eval_ctx,
+ &view_layer->layer_collections,
+ NULL);
+ layer_eval_layer_collection_post(view_layer);
+}
+
+void BKE_layer_eval_view_layer_indexed(const struct EvaluationContext *eval_ctx,
+ struct ID *owner_id,
+ int view_layer_index)
+{
+ BLI_assert(GS(owner_id->name) == ID_SCE);
+ BLI_assert(view_layer_index >= 0);
+ Scene *scene = (Scene *)owner_id;
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, view_layer_index);
+ BLI_assert(view_layer != NULL);
+ BKE_layer_eval_view_layer(eval_ctx, owner_id, view_layer);
+}
+
/**
* Free any static allocated memory.
*/
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 75a288092d8..f7f0991238f 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -849,6 +849,7 @@ void BKE_libblock_management_main_add(Main *bmain, void *idv)
new_id(lb, id, NULL);
/* alphabetic insertion: is in new_id */
id->tag &= ~(LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT);
+ bmain->is_memfile_undo_written = false;
BKE_main_unlock(bmain);
}
@@ -868,6 +869,7 @@ void BKE_libblock_management_main_remove(Main *bmain, void *idv)
BKE_main_lock(bmain);
BLI_remlink(lb, id);
id->tag |= LIB_TAG_NO_MAIN;
+ bmain->is_memfile_undo_written = false;
BKE_main_unlock(bmain);
}
@@ -1244,6 +1246,7 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl
BKE_main_lock(bmain);
BLI_addtail(lb, id);
new_id(lb, id, name);
+ bmain->is_memfile_undo_written = false;
/* alphabetic insertion: is in new_id */
BKE_main_unlock(bmain);
@@ -2144,7 +2147,7 @@ void BKE_library_make_local(
GSet *loop_tags = BLI_gset_ptr_new(__func__);
for (LinkNode *it = todo_ids; it; it = it->next) {
library_make_local_copying_check(it->link, loop_tags, bmain->relations, done_ids);
- BLI_assert(BLI_gset_size(loop_tags) == 0);
+ BLI_assert(BLI_gset_len(loop_tags) == 0);
}
BLI_gset_free(loop_tags, NULL);
BLI_gset_free(done_ids, NULL);
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index da765ca45af..953db6f3cb0 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -52,7 +52,7 @@
#include "DNA_movieclip_types.h"
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_lightprobe_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
@@ -422,10 +422,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
library_foreach_ID_as_subdata_link((ID **)&scene->nodetree, callback, user_data, flag, &data);
}
- /* DO NOT handle scene->basact here, it's doubling with the loop over whole scene->base later,
- * since basact is just a pointer to one of those items. */
- CALLBACK_INVOKE(scene->obedit, IDWALK_CB_NOP);
-
if (scene->ed) {
Sequence *seq;
SEQP_BEGIN(scene->ed, seq)
@@ -445,13 +441,13 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
CALLBACK_INVOKE(scene->gpd, IDWALK_CB_USER);
- FOREACH_SCENE_COLLECTION(scene, sc)
+ FOREACH_SCENE_COLLECTION_BEGIN(scene, sc)
{
for (LinkData *link = sc->objects.first; link; link = link->next) {
CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER);
}
}
- FOREACH_SCENE_COLLECTION_END
+ FOREACH_SCENE_COLLECTION_END;
ViewLayer *view_layer;
for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
@@ -685,6 +681,9 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
}
CALLBACK_INVOKE(material->group, IDWALK_CB_USER);
CALLBACK_INVOKE(material->edit_image, IDWALK_CB_USER);
+ if (material->texpaintslot != NULL) {
+ CALLBACK_INVOKE(material->texpaintslot->ima, IDWALK_CB_NOP);
+ }
break;
}
@@ -777,7 +776,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
case ID_GR:
{
Group *group = (Group *) id;
- FOREACH_GROUP_BASE(group, base)
+ FOREACH_GROUP_BASE_BEGIN(group, base)
{
CALLBACK_INVOKE(base->object, IDWALK_CB_USER_ONE);
}
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index 87e45990a6c..2c6df24f762 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -281,6 +281,26 @@ static void libblock_remap_data_preprocess_scene_object_unlink(
}
}
+static void libblock_remap_data_preprocess_group_unlink(
+ IDRemap *r_id_remap_data, Object *ob, const bool skip_indirect, const bool is_indirect)
+{
+ Main *bmain = r_id_remap_data->bmain;
+ for (Group *group = bmain->group.first; group; group = group->id.next) {
+ if (BKE_group_object_exists(group, ob)) {
+ if (skip_indirect && is_indirect) {
+ r_id_remap_data->skipped_indirect++;
+ r_id_remap_data->skipped_refcounted++;
+ }
+ else {
+ BKE_collections_object_remove(bmain, &group->id, ob, false);
+ if (!is_indirect) {
+ r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
+ }
+ }
+ }
+ }
+}
+
static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
{
switch (GS(r_id_remap_data->id->name)) {
@@ -295,19 +315,24 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
/* In case we are unlinking... */
if (!r_id_remap_data->old_id) {
/* ... everything from scene. */
- FOREACH_SCENE_OBJECT(sce, ob_iter)
+ FOREACH_SCENE_OBJECT_BEGIN(sce, ob_iter)
{
libblock_remap_data_preprocess_scene_object_unlink(
r_id_remap_data, sce, ob_iter, skip_indirect, is_indirect);
+ libblock_remap_data_preprocess_group_unlink(
+ r_id_remap_data, ob_iter, skip_indirect, is_indirect);
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
}
else if (GS(r_id_remap_data->old_id->name) == ID_OB) {
/* ... a specific object from scene. */
Object *old_ob = (Object *)r_id_remap_data->old_id;
libblock_remap_data_preprocess_scene_object_unlink(
r_id_remap_data, sce, old_ob, skip_indirect, is_indirect);
+ libblock_remap_data_preprocess_group_unlink(
+ r_id_remap_data, old_ob, skip_indirect, is_indirect);
}
+
}
break;
}
@@ -368,7 +393,7 @@ static void libblock_remap_data_postprocess_group_scene_unlink(Main *UNUSED(bmai
{
/* Note that here we assume no object has no base (i.e. all objects are assumed instanced
* in one scene...). */
- FOREACH_SCENE_OBJECT(sce, ob)
+ FOREACH_SCENE_OBJECT_BEGIN(sce, ob)
{
if (ob->flag & OB_FROMGROUP) {
Group *grp = BKE_group_object_find(NULL, ob);
@@ -382,7 +407,7 @@ static void libblock_remap_data_postprocess_group_scene_unlink(Main *UNUSED(bmai
}
}
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
}
static void libblock_remap_data_postprocess_obdata_relink(Main *UNUSED(bmain), Object *ob, ID *new_id)
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 2fc4c81cb0b..dd1315fe3fa 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -47,7 +47,6 @@
#include "BKE_colorband.h"
#include "BKE_context.h"
#include "BKE_freestyle.h"
-#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_linestyle.h"
#include "BKE_node.h"
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 3256c16e2f6..ba5a6a25048 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -51,7 +51,7 @@
#include "BKE_animsys.h"
#include "BKE_curve.h"
-#include "BKE_global.h"
+
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_mask.h"
diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c
index f60d87f2464..61c136d2c4f 100644
--- a/source/blender/blenkernel/intern/mask_evaluate.c
+++ b/source/blender/blenkernel/intern/mask_evaluate.c
@@ -42,12 +42,10 @@
#include "DNA_mask_types.h"
#include "BKE_curve.h"
-#include "BKE_global.h"
#include "BKE_mask.h"
#include "DEG_depsgraph.h"
-
unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height)
{
float max_segment = 0.01f;
@@ -898,11 +896,9 @@ void BKE_mask_layer_evaluate_deform(MaskLayer *masklay, const float ctime)
}
}
-#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-
void BKE_mask_eval_animation(struct EvaluationContext *eval_ctx, Mask *mask)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, mask->id.name, mask);
+ DEG_debug_print_eval(__func__, mask->id.name, mask);
for (MaskLayer *mask_layer = mask->masklayers.first;
mask_layer != NULL;
mask_layer = mask_layer->next)
@@ -913,7 +909,7 @@ void BKE_mask_eval_animation(struct EvaluationContext *eval_ctx, Mask *mask)
void BKE_mask_eval_update(struct EvaluationContext *eval_ctx, Mask *mask)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, mask->id.name, mask);
+ DEG_debug_print_eval(__func__, mask->id.name, mask);
for (MaskLayer *mask_layer = mask->masklayers.first;
mask_layer != NULL;
mask_layer = mask_layer->next)
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 7235aa0aaf6..2971f56c775 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -72,6 +72,7 @@
#include "BKE_editmesh.h"
#include "BKE_font.h"
+#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "GPU_material.h"
@@ -98,6 +99,9 @@ void BKE_material_free(Material *ma)
MEM_SAFE_FREE(ma->ramp_col);
MEM_SAFE_FREE(ma->ramp_spec);
+
+ /* Free gpu material before the ntree */
+ GPU_material_free(&ma->gpumaterial);
/* is no lib link block, but material extension */
if (ma->nodetree) {
@@ -108,8 +112,6 @@ void BKE_material_free(Material *ma)
MEM_SAFE_FREE(ma->texpaintslot);
- GPU_material_free(&ma->gpumaterial);
-
BKE_icon_id_delete((ID *)ma);
BKE_previewimg_free(&ma->preview);
}
@@ -259,6 +261,10 @@ void BKE_material_copy_data(Main *bmain, Material *ma_dst, const Material *ma_sr
ma_dst->preview = NULL;
}
+ if (ma_src->texpaintslot != NULL) {
+ ma_dst->texpaintslot = MEM_dupallocN(ma_src->texpaintslot);
+ }
+
BLI_listbase_clear(&ma_dst->gpumaterial);
/* TODO Duplicate Engine Settings and set runtime to NULL */
@@ -1709,13 +1715,14 @@ void paste_matcopybuf(Material *ma)
MEM_freeN(mtex);
}
+ /* Free gpu material before the ntree */
+ GPU_material_free(&ma->gpumaterial);
+
if (ma->nodetree) {
ntreeFreeTree(ma->nodetree);
MEM_freeN(ma->nodetree);
}
- GPU_material_free(&ma->gpumaterial);
-
id = (ma->id);
memcpy(ma, &matcopybuf, sizeof(Material));
(ma->id) = id;
@@ -1772,9 +1779,7 @@ bool BKE_object_material_edit_image_set(Object *ob, short mat_nr, Image *image)
void BKE_material_eval(const struct EvaluationContext *UNUSED(eval_ctx), Material *material)
{
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s (%p)\n", __func__, material->id.name, material);
- }
+ DEG_debug_print_eval(__func__, material->id.name, material);
if ((BLI_listbase_is_empty(&material->gpumaterial) == false)) {
GPU_material_uniform_buffer_tag_dirty(&material->gpumaterial);
}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 5a0ac86823f..cc801b2d8c3 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -549,9 +549,9 @@ void BKE_mball_eval_geometry(const struct EvaluationContext *UNUSED(eval_ctx),
/* Draw Engine */
/* use for draw-manager only. */
-void BKE_mball_element_calc_display_m3x4(float r_scale_xform[3][4],
- const float obmat[4][4],
- const float local_pos[3])
+void BKE_mball_element_calc_scale_xform(float r_scale_xform[3][4],
+ const float obmat[4][4],
+ const float local_pos[3])
{
float world_pos[3], scamat[3][3];
mul_v3_m4v3(world_pos, obmat, local_pos);
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 3217c234718..af92422f4c3 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -66,6 +66,7 @@
#include "BKE_editmesh.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
/* Define for cases when you want extra validation of mesh
* after certain modifications.
@@ -1044,7 +1045,7 @@ static void make_edges_mdata_extend(MEdge **r_alledge, int *r_totedge,
BKE_mesh_poly_edgehash_insert(eh, mp, mloop + mp->loopstart);
}
- totedge_new = BLI_edgehash_size(eh);
+ totedge_new = BLI_edgehash_len(eh);
#ifdef DEBUG
/* ensure that theres no overlap! */
@@ -2205,6 +2206,8 @@ static int split_faces_prepare_new_verts(
MLoop *ml = mloop;
MLoopNorSpace **lnor_space = lnors_spacearr->lspacearr;
+ BLI_assert(lnors_spacearr->data_type == MLNOR_SPACEARR_LOOP_INDEX);
+
for (int loop_idx = 0; loop_idx < num_loops; loop_idx++, ml++, lnor_space++) {
if (!BLI_BITMAP_TEST(done_loops, loop_idx)) {
const int vert_idx = ml->v;
@@ -2214,7 +2217,15 @@ static int split_faces_prepare_new_verts(
BLI_assert(*lnor_space);
- if ((*lnor_space)->loops) {
+ if ((*lnor_space)->flags & MLNOR_SPACE_IS_SINGLE) {
+ /* Single loop in this fan... */
+ BLI_assert(GET_INT_FROM_POINTER((*lnor_space)->loops) == loop_idx);
+ BLI_BITMAP_ENABLE(done_loops, loop_idx);
+ if (vert_used) {
+ ml->v = new_vert_idx;
+ }
+ }
+ else {
for (LinkNode *lnode = (*lnor_space)->loops; lnode; lnode = lnode->next) {
const int ml_fan_idx = GET_INT_FROM_POINTER(lnode->link);
BLI_BITMAP_ENABLE(done_loops, ml_fan_idx);
@@ -2223,13 +2234,6 @@ static int split_faces_prepare_new_verts(
}
}
}
- else {
- /* Single loop in this fan... */
- BLI_BITMAP_ENABLE(done_loops, loop_idx);
- if (vert_used) {
- ml->v = new_vert_idx;
- }
- }
if (!vert_used) {
BLI_BITMAP_ENABLE(verts_used, vert_idx);
@@ -2425,12 +2429,12 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
/* settings: 1 - preview, 2 - render */
Mesh *BKE_mesh_new_from_object(
const EvaluationContext *eval_ctx, Main *bmain, Scene *sce, Object *ob,
- int apply_modifiers, int settings, int calc_tessface, int calc_undeformed)
+ int apply_modifiers, int calc_tessface, int calc_undeformed)
{
Mesh *tmpmesh;
Curve *tmpcu = NULL, *copycu;
int i;
- const bool render = (settings == eModifierMode_Render);
+ const bool render = (DEG_get_mode(eval_ctx->depsgraph) == DAG_EVAL_RENDER);
const bool cage = !apply_modifiers;
bool do_mat_id_data_us = true;
@@ -2466,7 +2470,7 @@ Mesh *BKE_mesh_new_from_object(
/* if getting the original caged mesh, delete object modifiers */
if (cage)
- BKE_object_free_modifiers(tmpobj);
+ BKE_object_free_modifiers(tmpobj, 0);
/* copies the data */
copycu = tmpobj->data = BKE_curve_copy(bmain, (Curve *) ob->data);
@@ -2667,9 +2671,7 @@ Mesh *BKE_mesh_new_from_object(
void BKE_mesh_eval_geometry(const EvaluationContext *UNUSED(eval_ctx),
Mesh *mesh)
{
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s\n", __func__, mesh->id.name);
- }
+ DEG_debug_print_eval(__func__, mesh->id.name, mesh);
if (mesh->bb == NULL || (mesh->bb->flag & BOUNDBOX_DIRTY)) {
BKE_mesh_texspace_calc(mesh);
}
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 00d1b29caf8..01cee2a19ff 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -43,7 +43,7 @@
#include "BLI_math.h"
#include "BLI_edgehash.h"
#include "BLI_bitmap.h"
-#include "BLI_polyfill2d.h"
+#include "BLI_polyfill_2d.h"
#include "BLI_linklist.h"
#include "BLI_linklist_stack.h"
#include "BLI_alloca.h"
@@ -253,16 +253,6 @@ static void mesh_calc_normals_poly_prepare_cb(
}
}
-static void mesh_calc_normals_poly_accum_cb(
- void *__restrict userdata,
- const int lidx,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- MeshCalcNormalsData *data = userdata;
-
- add_v3_v3(data->vnors[data->mloop[lidx].v], data->lnors_weighted[lidx]);
-}
-
static void mesh_calc_normals_poly_finalize_cb(
void *__restrict userdata,
const int vidx,
@@ -327,7 +317,11 @@ void BKE_mesh_calc_normals_poly(
BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_prepare_cb, &settings);
/* Actually accumulate weighted loop normals into vertex ones. */
- BLI_task_parallel_range(0, numLoops, &data, mesh_calc_normals_poly_accum_cb, &settings);
+ /* Unfortunately, not possible to thread that (not in a reasonable, totally lock- and barrier-free fashion),
+ * since several loops will point to the same vertex... */
+ for (int lidx = 0; lidx < numLoops; lidx++) {
+ add_v3_v3(vnors[mloop[lidx].v], data.lnors_weighted[lidx]);
+ }
/* Normalize and validate computed vertex normals. */
BLI_task_parallel_range(0, numVerts, &data, mesh_calc_normals_poly_finalize_cb, &settings);
@@ -450,7 +444,7 @@ cleanup:
MEM_freeN(fnors);
}
-void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoops)
+void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoops, const char data_type)
{
if (!(lnors_spacearr->lspacearr && lnors_spacearr->loops_pool)) {
MemArena *mem;
@@ -462,6 +456,8 @@ void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoo
lnors_spacearr->lspacearr = BLI_memarena_calloc(mem, sizeof(MLoopNorSpace *) * (size_t)numLoops);
lnors_spacearr->loops_pool = BLI_memarena_alloc(mem, sizeof(LinkNode) * (size_t)numLoops);
}
+ BLI_assert(ELEM(data_type, MLNOR_SPACEARR_BMLOOP_PTR, MLNOR_SPACEARR_LOOP_INDEX));
+ lnors_spacearr->data_type = data_type;
}
void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr)
@@ -555,12 +551,32 @@ void BKE_lnor_space_define(MLoopNorSpace *lnor_space, const float lnor[3],
}
}
-void BKE_lnor_space_add_loop(MLoopNorSpaceArray *lnors_spacearr, MLoopNorSpace *lnor_space, const int ml_index,
- const bool do_add_loop)
+/**
+ * Add a new given loop to given lnor_space.
+ * Depending on \a lnor_space->data_type, we expect \a bm_loop to be a pointer to BMLoop struct (in case of BMLOOP_PTR),
+ * or NULL (in case of LOOP_INDEX), loop index is then stored in pointer.
+ * If \a is_single is set, the BMLoop or loop index is directly stored in \a lnor_space->loops pointer (since there
+ * is only one loop in this fan), else it is added to the linked list of loops in the fan.
+ */
+void BKE_lnor_space_add_loop(
+ MLoopNorSpaceArray *lnors_spacearr, MLoopNorSpace *lnor_space,
+ const int ml_index, void *bm_loop, const bool is_single)
{
+ BLI_assert((lnors_spacearr->data_type == MLNOR_SPACEARR_LOOP_INDEX && bm_loop == NULL) ||
+ (lnors_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR && bm_loop != NULL));
+
lnors_spacearr->lspacearr[ml_index] = lnor_space;
- if (do_add_loop) {
- BLI_linklist_prepend_nlink(&lnor_space->loops, SET_INT_IN_POINTER(ml_index), &lnors_spacearr->loops_pool[ml_index]);
+ if (bm_loop == NULL) {
+ bm_loop = SET_INT_IN_POINTER(ml_index);
+ }
+ if (is_single) {
+ BLI_assert(lnor_space->loops == NULL);
+ lnor_space->flags |= MLNOR_SPACE_IS_SINGLE;
+ lnor_space->loops = bm_loop;
+ }
+ else {
+ BLI_assert((lnor_space->flags & MLNOR_SPACE_IS_SINGLE) == 0);
+ BLI_linklist_prepend_nlink(&lnor_space->loops, bm_loop, &lnors_spacearr->loops_pool[ml_index]);
}
}
@@ -686,10 +702,11 @@ typedef struct LoopSplitTaskDataCommon {
const MEdge *medges;
const MLoop *mloops;
const MPoly *mpolys;
- const int (*edge_to_loops)[2];
- const int *loop_to_poly;
+ int (*edge_to_loops)[2];
+ int *loop_to_poly;
const float (*polynors)[3];
+ int numEdges;
int numLoops;
int numPolys;
} LoopSplitTaskDataCommon;
@@ -699,7 +716,154 @@ typedef struct LoopSplitTaskDataCommon {
/* See comment about edge_to_loops below. */
#define IS_EDGE_SHARP(_e2l) (ELEM((_e2l)[1], INDEX_UNSET, INDEX_INVALID))
-static void loop_manifold_fan_around_vert_next(
+static void mesh_edges_sharp_tag(
+ LoopSplitTaskDataCommon *data,
+ const bool check_angle, const float split_angle, const bool do_sharp_edges_tag)
+{
+ const MVert *mverts = data->mverts;
+ const MEdge *medges = data->medges;
+ const MLoop *mloops = data->mloops;
+
+ const MPoly *mpolys = data->mpolys;
+
+ const int numEdges = data->numEdges;
+ const int numPolys = data->numPolys;
+
+ float (*loopnors)[3] = data->loopnors; /* Note: loopnors may be NULL here. */
+ const float (*polynors)[3] = data->polynors;
+
+ int (*edge_to_loops)[2] = data->edge_to_loops;
+ int *loop_to_poly = data->loop_to_poly;
+
+ BLI_bitmap *sharp_edges = do_sharp_edges_tag ? BLI_BITMAP_NEW(numEdges, __func__) : NULL;
+
+ const MPoly *mp;
+ int mp_index;
+
+ const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f;
+
+ for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) {
+ const MLoop *ml_curr;
+ int *e2l;
+ int ml_curr_index = mp->loopstart;
+ const int ml_last_index = (ml_curr_index + mp->totloop) - 1;
+
+ ml_curr = &mloops[ml_curr_index];
+
+ for (; ml_curr_index <= ml_last_index; ml_curr++, ml_curr_index++) {
+ e2l = edge_to_loops[ml_curr->e];
+
+ loop_to_poly[ml_curr_index] = mp_index;
+
+ /* Pre-populate all loop normals as if their verts were all-smooth, this way we don't have to compute
+ * those later!
+ */
+ if (loopnors) {
+ normal_short_to_float_v3(loopnors[ml_curr_index], mverts[ml_curr->v].no);
+ }
+
+ /* Check whether current edge might be smooth or sharp */
+ if ((e2l[0] | e2l[1]) == 0) {
+ /* 'Empty' edge until now, set e2l[0] (and e2l[1] to INDEX_UNSET to tag it as unset). */
+ e2l[0] = ml_curr_index;
+ /* We have to check this here too, else we might miss some flat faces!!! */
+ e2l[1] = (mp->flag & ME_SMOOTH) ? INDEX_UNSET : INDEX_INVALID;
+ }
+ else if (e2l[1] == INDEX_UNSET) {
+ const bool is_angle_sharp = (check_angle &&
+ dot_v3v3(polynors[loop_to_poly[e2l[0]]], polynors[mp_index]) < split_angle_cos);
+
+ /* Second loop using this edge, time to test its sharpness.
+ * An edge is sharp if it is tagged as such, or its face is not smooth,
+ * or both poly have opposed (flipped) normals, i.e. both loops on the same edge share the same vertex,
+ * or angle between both its polys' normals is above split_angle value.
+ */
+ if (!(mp->flag & ME_SMOOTH) || (medges[ml_curr->e].flag & ME_SHARP) ||
+ ml_curr->v == mloops[e2l[0]].v ||
+ is_angle_sharp)
+ {
+ /* Note: we are sure that loop != 0 here ;) */
+ e2l[1] = INDEX_INVALID;
+
+ /* We want to avoid tagging edges as sharp when it is already defined as such by
+ * other causes than angle threshold... */
+ if (do_sharp_edges_tag && is_angle_sharp) {
+ BLI_BITMAP_SET(sharp_edges, ml_curr->e, true);
+ }
+ }
+ else {
+ e2l[1] = ml_curr_index;
+ }
+ }
+ else if (!IS_EDGE_SHARP(e2l)) {
+ /* More than two loops using this edge, tag as sharp if not yet done. */
+ e2l[1] = INDEX_INVALID;
+
+ /* We want to avoid tagging edges as sharp when it is already defined as such by
+ * other causes than angle threshold... */
+ if (do_sharp_edges_tag) {
+ BLI_BITMAP_SET(sharp_edges, ml_curr->e, false);
+ }
+ }
+ /* Else, edge is already 'disqualified' (i.e. sharp)! */
+ }
+ }
+
+ /* If requested, do actual tagging of edges as sharp in another loop. */
+ if (do_sharp_edges_tag) {
+ MEdge *me;
+ int me_index;
+ for (me = (MEdge *)medges, me_index = 0; me_index < numEdges; me++, me_index++) {
+ if (BLI_BITMAP_TEST(sharp_edges, me_index)) {
+ me->flag |= ME_SHARP;
+ }
+ }
+
+ MEM_freeN(sharp_edges);
+ }
+}
+
+/** Define sharp edges as needed to mimic 'autosmooth' from angle threshold.
+ *
+ * Used when defining an empty custom loop normals data layer, to keep same shading as with autosmooth!
+ */
+void BKE_edges_sharp_from_angle_set(
+ const struct MVert *mverts, const int UNUSED(numVerts),
+ struct MEdge *medges, const int numEdges,
+ struct MLoop *mloops, const int numLoops,
+ struct MPoly *mpolys, const float (*polynors)[3], const int numPolys,
+ const float split_angle)
+{
+ if (split_angle >= (float)M_PI) {
+ /* Nothing to do! */
+ return;
+ }
+
+ /* Mapping edge -> loops. See BKE_mesh_normals_loop_split() for details. */
+ int (*edge_to_loops)[2] = MEM_calloc_arrayN((size_t)numEdges, sizeof(*edge_to_loops), __func__);
+
+ /* Simple mapping from a loop to its polygon index. */
+ int *loop_to_poly = MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__);
+
+ LoopSplitTaskDataCommon common_data = {
+ .mverts = mverts,
+ .medges = medges,
+ .mloops = mloops,
+ .mpolys = mpolys,
+ .edge_to_loops = edge_to_loops,
+ .loop_to_poly = loop_to_poly,
+ .polynors = polynors,
+ .numEdges = numEdges,
+ .numPolys = numPolys,
+ };
+
+ mesh_edges_sharp_tag(&common_data, true, split_angle, true);
+
+ MEM_freeN(edge_to_loops);
+ MEM_freeN(loop_to_poly);
+}
+
+void BKE_mesh_loop_manifold_fan_around_vert_next(
const MLoop *mloops, const MPoly *mpolys,
const int *loop_to_poly, const int *e2lfan_curr, const uint mv_pivot_index,
const MLoop **r_mlfan_curr, int *r_mlfan_curr_index, int *r_mlfan_vert_index, int *r_mpfan_curr_index)
@@ -788,7 +952,7 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS
BKE_lnor_space_define(lnor_space, *lnor, vec_curr, vec_prev, NULL);
/* We know there is only one loop in this space, no need to create a linklist in this case... */
- BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, ml_curr_index, false);
+ BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, ml_curr_index, NULL, true);
if (clnors_data) {
BKE_lnor_space_custom_data_to_normal(lnor_space, clnors_data[ml_curr_index], *lnor);
@@ -921,7 +1085,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
if (lnors_spacearr) {
/* Assign current lnor space to current 'vertex' loop. */
- BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, mlfan_vert_index, true);
+ BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, mlfan_vert_index, NULL, false);
if (me_curr != me_org) {
/* We store here all edges-normalized vectors processed. */
BLI_stack_push(edge_vectors, vec_curr);
@@ -939,7 +1103,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
copy_v3_v3(vec_prev, vec_curr);
/* Find next loop of the smooth fan. */
- loop_manifold_fan_around_vert_next(
+ BKE_mesh_loop_manifold_fan_around_vert_next(
mloops, mpolys, loop_to_poly, e2lfan_curr, mv_pivot_index,
&mlfan_curr, &mlfan_curr_index, &mlfan_vert_index, &mpfan_curr_index);
@@ -1076,7 +1240,7 @@ static bool loop_split_generator_check_cyclic_smooth_fan(
while (true) {
/* Find next loop of the smooth fan. */
- loop_manifold_fan_around_vert_next(
+ BKE_mesh_loop_manifold_fan_around_vert_next(
mloops, mpolys, loop_to_poly, e2lfan_curr, mv_pivot_index,
&mlfan_curr, &mlfan_curr_index, &mlfan_vert_index, &mpfan_curr_index);
@@ -1270,7 +1434,7 @@ void BKE_mesh_normals_loop_split(
const MVert *mverts, const int UNUSED(numVerts), MEdge *medges, const int numEdges,
MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
MPoly *mpolys, const float (*polynors)[3], const int numPolys,
- const bool use_split_normals, float split_angle,
+ const bool use_split_normals, const float split_angle,
MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], int *r_loop_to_poly)
{
/* For now this is not supported. If we do not use split normals, we do not generate anything fancy! */
@@ -1319,9 +1483,6 @@ void BKE_mesh_normals_loop_split(
/* Simple mapping from a loop to its polygon index. */
int *loop_to_poly = r_loop_to_poly ? r_loop_to_poly : MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__);
- MPoly *mp;
- int mp_index;
-
/* When using custom loop normals, disable the angle feature! */
const bool check_angle = (split_angle < (float)M_PI) && (clnors_data == NULL);
@@ -1331,67 +1492,12 @@ void BKE_mesh_normals_loop_split(
TIMEIT_START_AVERAGED(BKE_mesh_normals_loop_split);
#endif
- if (check_angle) {
- split_angle = cosf(split_angle);
- }
-
if (!r_lnors_spacearr && clnors_data) {
/* We need to compute lnor spacearr if some custom lnor data are given to us! */
r_lnors_spacearr = &_lnors_spacearr;
}
if (r_lnors_spacearr) {
- BKE_lnor_spacearr_init(r_lnors_spacearr, numLoops);
- }
-
- /* This first loop check which edges are actually smooth, and compute edge vectors. */
- for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) {
- MLoop *ml_curr;
- int *e2l;
- int ml_curr_index = mp->loopstart;
- const int ml_last_index = (ml_curr_index + mp->totloop) - 1;
-
- ml_curr = &mloops[ml_curr_index];
-
- for (; ml_curr_index <= ml_last_index; ml_curr++, ml_curr_index++) {
- e2l = edge_to_loops[ml_curr->e];
-
- loop_to_poly[ml_curr_index] = mp_index;
-
- /* Pre-populate all loop normals as if their verts were all-smooth, this way we don't have to compute
- * those later!
- */
- normal_short_to_float_v3(r_loopnors[ml_curr_index], mverts[ml_curr->v].no);
-
- /* Check whether current edge might be smooth or sharp */
- if ((e2l[0] | e2l[1]) == 0) {
- /* 'Empty' edge until now, set e2l[0] (and e2l[1] to INDEX_UNSET to tag it as unset). */
- e2l[0] = ml_curr_index;
- /* We have to check this here too, else we might miss some flat faces!!! */
- e2l[1] = (mp->flag & ME_SMOOTH) ? INDEX_UNSET : INDEX_INVALID;
- }
- else if (e2l[1] == INDEX_UNSET) {
- /* Second loop using this edge, time to test its sharpness.
- * An edge is sharp if it is tagged as such, or its face is not smooth,
- * or both poly have opposed (flipped) normals, i.e. both loops on the same edge share the same vertex,
- * or angle between both its polys' normals is above split_angle value.
- */
- if (!(mp->flag & ME_SMOOTH) || (medges[ml_curr->e].flag & ME_SHARP) ||
- ml_curr->v == mloops[e2l[0]].v ||
- (check_angle && dot_v3v3(polynors[loop_to_poly[e2l[0]]], polynors[mp_index]) < split_angle))
- {
- /* Note: we are sure that loop != 0 here ;) */
- e2l[1] = INDEX_INVALID;
- }
- else {
- e2l[1] = ml_curr_index;
- }
- }
- else if (!IS_EDGE_SHARP(e2l)) {
- /* More than two loops using this edge, tag as sharp if not yet done. */
- e2l[1] = INDEX_INVALID;
- }
- /* Else, edge is already 'disqualified' (i.e. sharp)! */
- }
+ BKE_lnor_spacearr_init(r_lnors_spacearr, numLoops, MLNOR_SPACEARR_LOOP_INDEX);
}
/* Init data common to all tasks. */
@@ -1403,13 +1509,17 @@ void BKE_mesh_normals_loop_split(
.medges = medges,
.mloops = mloops,
.mpolys = mpolys,
- .edge_to_loops = (const int(*)[2])edge_to_loops,
+ .edge_to_loops = edge_to_loops,
.loop_to_poly = loop_to_poly,
.polynors = polynors,
+ .numEdges = numEdges,
.numLoops = numLoops,
.numPolys = numPolys,
};
+ /* This first loop check which edges are actually smooth, and compute edge vectors. */
+ mesh_edges_sharp_tag(&common_data, check_angle, split_angle, false);
+
if (numLoops < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) {
/* Not enough loops to be worth the whole threading overhead... */
loop_split_generator(NULL, &common_data);
@@ -1501,6 +1611,8 @@ static void mesh_normals_loop_custom_set(
}
}
+ BLI_assert(lnors_spacearr.data_type == MLNOR_SPACEARR_LOOP_INDEX);
+
/* Now, check each current smooth fan (one lnor space per smooth fan!), and if all its matching custom lnors
* are not (enough) equal, add sharp edges as needed.
* This way, next time we run BKE_mesh_normals_loop_split(), we'll get lnor spacearr/smooth fans matching
@@ -1524,7 +1636,7 @@ static void mesh_normals_loop_custom_set(
if (!BLI_BITMAP_TEST(done_loops, i)) {
/* Notes:
- * * In case of mono-loop smooth fan, loops is NULL, so everything is fine (we have nothing to do).
+ * * In case of mono-loop smooth fan, we have nothing to do.
* * Loops in this linklist are ordered (in reversed order compared to how they were discovered by
* BKE_mesh_normals_loop_split(), but this is not a problem). Which means if we find a
* mismatching clnor, we know all remaining loops will have to be in a new, different smooth fan/
@@ -1532,6 +1644,11 @@ static void mesh_normals_loop_custom_set(
* * In smooth fan case, we compare each clnor against a ref one, to avoid small differences adding
* up into a real big one in the end!
*/
+ if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) {
+ BLI_BITMAP_ENABLE(done_loops, i);
+ continue;
+ }
+
LinkNode *loops = lnors_spacearr.lspacearr[i]->loops;
MLoop *prev_ml = NULL;
const float *org_nor = NULL;
@@ -1579,9 +1696,6 @@ static void mesh_normals_loop_custom_set(
medges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e].flag |= ME_SHARP;
}
}
-
- /* For single loops, where lnors_spacearr.lspacearr[i]->loops is NULL. */
- BLI_BITMAP_ENABLE(done_loops, i);
}
}
@@ -1611,7 +1725,15 @@ static void mesh_normals_loop_custom_set(
* computed 2D factors).
*/
LinkNode *loops = lnors_spacearr.lspacearr[i]->loops;
- if (loops) {
+ if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) {
+ BLI_assert(GET_INT_FROM_POINTER(loops) == i);
+ const int nidx = use_vertices ? (int)mloops[i].v : i;
+ float *nor = r_custom_loopnors[nidx];
+
+ BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], nor, r_clnors_data[i]);
+ BLI_BITMAP_DISABLE(done_loops, i);
+ }
+ else {
int nbr_nors = 0;
float avg_nor[3];
short clnor_data_tmp[2], *clnor_data;
@@ -1638,13 +1760,6 @@ static void mesh_normals_loop_custom_set(
clnor_data[1] = clnor_data_tmp[1];
}
}
- else {
- const int nidx = use_vertices ? (int)mloops[i].v : i;
- float *nor = r_custom_loopnors[nidx];
-
- BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], nor, r_clnors_data[i]);
- BLI_BITMAP_DISABLE(done_loops, i);
- }
}
}
@@ -2272,6 +2387,7 @@ void BKE_mesh_calc_volume(
}
}
+/** \} */
/* -------------------------------------------------------------------- */
@@ -2798,9 +2914,22 @@ void BKE_mesh_recalc_looptri(
}
else if (mp_totloop == 4) {
ML_TO_MLT(0, 1, 2);
+ MLoopTri *mlt_a = mlt;
mlooptri_index++;
ML_TO_MLT(0, 2, 3);
+ MLoopTri *mlt_b = mlt;
mlooptri_index++;
+
+ if (UNLIKELY(is_quad_flip_v3_first_third_fast(
+ mvert[mloop[mlt_a->tri[0]].v].co,
+ mvert[mloop[mlt_a->tri[1]].v].co,
+ mvert[mloop[mlt_a->tri[2]].v].co,
+ mvert[mloop[mlt_b->tri[2]].v].co)))
+ {
+ /* flip out of degenerate 0-2 state. */
+ mlt_a->tri[2] = mlt_b->tri[2];
+ mlt_b->tri[0] = mlt_a->tri[1];
+ }
}
#endif /* USE_TESSFACE_SPEEDUP */
else {
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
index f321c94bf00..0af4dae4506 100644
--- a/source/blender/blenkernel/intern/mesh_remap.c
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -36,7 +36,7 @@
#include "BLI_bitmap.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
-#include "BLI_polyfill2d.h"
+#include "BLI_polyfill_2d.h"
#include "BLI_rand.h"
#include "BKE_bvhutils.h"
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index 54de843bc64..8301b6a42b1 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -63,8 +63,8 @@ typedef union {
} EdgeUUID;
typedef struct SortFace {
- EdgeUUID es[4];
- unsigned int index;
+ EdgeUUID es[4];
+ unsigned int index;
} SortFace;
/* Used to detect polys (faces) using exactly the same vertices. */
@@ -127,28 +127,28 @@ static int search_face_cmp(const void *v1, const void *v2)
if (sfa->es[0].edval > sfb->es[0].edval) {
return 1;
}
- else if (sfa->es[0].edval < sfb->es[0].edval) {
+ else if (sfa->es[0].edval < sfb->es[0].edval) {
return -1;
}
- else if (sfa->es[1].edval > sfb->es[1].edval) {
+ else if (sfa->es[1].edval > sfb->es[1].edval) {
return 1;
}
- else if (sfa->es[1].edval < sfb->es[1].edval) {
+ else if (sfa->es[1].edval < sfb->es[1].edval) {
return -1;
}
- else if (sfa->es[2].edval > sfb->es[2].edval) {
+ else if (sfa->es[2].edval > sfb->es[2].edval) {
return 1;
}
- else if (sfa->es[2].edval < sfb->es[2].edval) {
+ else if (sfa->es[2].edval < sfb->es[2].edval) {
return -1;
}
- else if (sfa->es[3].edval > sfb->es[3].edval) {
+ else if (sfa->es[3].edval > sfb->es[3].edval) {
return 1;
}
- else if (sfa->es[3].edval < sfb->es[3].edval) {
+ else if (sfa->es[3].edval < sfb->es[3].edval) {
return -1;
}
@@ -1412,7 +1412,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool update, const bool select)
}
}
- totedge = BLI_edgehash_size(eh);
+ totedge = BLI_edgehash_len(eh);
/* write new edges into a temporary CustomData */
CustomData_reset(&edata);
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 8bfeacd256c..5eb5272f3e5 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -69,6 +69,8 @@
#include "BKE_main.h"
/* end */
+#include "DEG_depsgraph.h"
+
#include "MOD_modifiertypes.h"
static ModifierTypeInfo *modifier_types[NUM_MODIFIER_TYPES] = {NULL};
@@ -136,16 +138,38 @@ ModifierData *modifier_new(int type)
return md;
}
-void modifier_free(ModifierData *md)
+static void modifier_free_data_id_us_cb(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int cb_flag)
+{
+ ID *id = *idpoin;
+ if (id != NULL && (cb_flag & IDWALK_CB_USER) != 0) {
+ id_us_min(id);
+ }
+}
+
+void modifier_free_ex(ModifierData *md, const int flag)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ if (mti->foreachIDLink) {
+ mti->foreachIDLink(md, NULL, modifier_free_data_id_us_cb, NULL);
+ }
+ else if (mti->foreachObjectLink) {
+ mti->foreachObjectLink(md, NULL, (ObjectWalkFunc)modifier_free_data_id_us_cb, NULL);
+ }
+ }
+
if (mti->freeData) mti->freeData(md);
if (md->error) MEM_freeN(md->error);
MEM_freeN(md);
}
+void modifier_free(ModifierData *md)
+{
+ modifier_free_ex(md, 0);
+}
+
bool modifier_unique_name(ListBase *modifiers, ModifierData *md)
{
if (modifiers && md) {
@@ -666,9 +690,9 @@ bool modifiers_isCorrectableDeformed(struct Scene *scene, Object *ob)
ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
int required_mode = eModifierMode_Realtime;
- if (ob->mode == OB_MODE_EDIT)
+ if (ob->mode == OB_MODE_EDIT) {
required_mode |= eModifierMode_Editmode;
-
+ }
for (; md; md = md->next) {
if (!modifier_isEnabled(scene, md, required_mode)) {
/* pass */
diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c
index 0838630a6cb..a1172d3f110 100644
--- a/source/blender/blenkernel/intern/modifiers_bmesh.c
+++ b/source/blender/blenkernel/intern/modifiers_bmesh.c
@@ -62,7 +62,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal)
{
MVert *mv, *mvert;
MEdge *me, *medge;
- MPoly /* *mpoly, */ /* UNUSED */ *mp;
+ MPoly *mpoly, *mp;
MLoop *mloop;
BMVert *v, **vtable;
BMEdge *e, **etable;
@@ -70,7 +70,6 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal)
BMFace *f;
int i, j, totvert, totedge /* , totface */ /* UNUSED */ ;
bool is_init = (bm->totvert == 0) && (bm->totedge == 0) && (bm->totface == 0);
- bool is_cddm = (dm->type == DM_TYPE_CDDM); /* duplicate the arrays for non cddm */
char has_orig_htype = 0;
int cd_vert_bweight_offset;
@@ -106,7 +105,8 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal)
etable = MEM_mallocN(sizeof(*etable) * totedge, __func__);
/*do verts*/
- mv = mvert = is_cddm ? dm->getVertArray(dm) : dm->dupVertArray(dm);
+ bool vert_allocated;
+ mv = mvert = DM_get_vert_array(dm, &vert_allocated);;
for (i = 0; i < totvert; i++, mv++) {
v = BM_vert_create(bm, mv->co, NULL, BM_CREATE_SKIP_CD);
normal_short_to_float_v3(v->no, mv->no);
@@ -124,11 +124,12 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal)
*orig_index = ORIGINDEX_NONE;
}
}
- if (!is_cddm) MEM_freeN(mvert);
+ if (vert_allocated) MEM_freeN(mvert);
if (is_init) bm->elem_index_dirty &= ~BM_VERT;
/*do edges*/
- me = medge = is_cddm ? dm->getEdgeArray(dm) : dm->dupEdgeArray(dm);
+ bool edge_allocated;
+ me = medge = DM_get_edge_array(dm, &edge_allocated);
for (i = 0; i < totedge; i++, me++) {
//BLI_assert(BM_edge_exists(vtable[me->v1], vtable[me->v2]) == NULL);
e = BM_edge_create(bm, vtable[me->v1], vtable[me->v2], NULL, BM_CREATE_SKIP_CD);
@@ -147,13 +148,14 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal)
*orig_index = ORIGINDEX_NONE;
}
}
- if (!is_cddm) MEM_freeN(medge);
+ if (edge_allocated) MEM_freeN(medge);
if (is_init) bm->elem_index_dirty &= ~BM_EDGE;
/* do faces */
/* note: i_alt is aligned with bmesh faces which may not always align with mpolys */
- mp = dm->getPolyArray(dm);
- mloop = dm->getLoopArray(dm);
+ bool poly_allocated, loop_allocated;
+ mpoly = mp = DM_get_poly_array(dm, &poly_allocated);
+ mloop = DM_get_loop_array(dm, &loop_allocated);
face_normals = (dm->dirty & DM_DIRTY_NORMALS) ? NULL : CustomData_get_layer(&dm->polyData, CD_NORMAL);
for (i = 0; i < dm->numPolyData; i++, mp++) {
BMLoop *l_iter;
@@ -194,6 +196,8 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal)
*orig_index = ORIGINDEX_NONE;
}
}
+ if (poly_allocated) MEM_freeN(mpoly);
+ if (loop_allocated) MEM_freeN(mloop);
if (is_init) bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP);
MEM_freeN(vtable);
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index 08df976941b..9ed715d7591 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -73,12 +73,12 @@
#include "IMB_imbuf.h"
#include "IMB_moviecache.h"
+#include "DEG_depsgraph.h"
+
#ifdef WITH_OPENEXR
# include "intern/openexr/openexr_multi.h"
#endif
-#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-
/*********************** movieclip buffer loaders *************************/
static int sequence_guess_offset(const char *full_name, int head_len, unsigned short numlen)
@@ -926,7 +926,7 @@ static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip,
/* cache isn't threadsafe itself and also loading of movies
* can't happen from concurrent threads that's why we use lock here */
- BLI_lock_thread(LOCK_MOVIECLIP);
+ BLI_thread_lock(LOCK_MOVIECLIP);
/* try to obtain cached postprocessed frame first */
if (need_postprocessed_frame(user, postprocess_flag)) {
@@ -976,7 +976,7 @@ static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip,
}
}
- BLI_unlock_thread(LOCK_MOVIECLIP);
+ BLI_thread_unlock(LOCK_MOVIECLIP);
return ibuf;
}
@@ -1202,6 +1202,23 @@ int BKE_movieclip_get_duration(MovieClip *clip)
return clip->len;
}
+float BKE_movieclip_get_fps(MovieClip *clip)
+{
+ if (clip->source != MCLIP_SRC_MOVIE) {
+ return 0.0f;
+ }
+ movieclip_open_anim_file(clip);
+ if (clip->anim == NULL) {
+ return 0.0f;
+ }
+ short frs_sec;
+ float frs_sec_base;
+ if (IMB_anim_get_fps(clip->anim, &frs_sec, &frs_sec_base, true)) {
+ return (float)frs_sec / frs_sec_base;
+ }
+ return 0.0f;
+}
+
void BKE_movieclip_get_aspect(MovieClip *clip, float *aspx, float *aspy)
{
*aspx = 1.0;
@@ -1410,13 +1427,13 @@ static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, i
* could be solved in a way that thread only prepares memory
* buffer and write to disk happens separately
*/
- BLI_lock_thread(LOCK_MOVIECLIP);
+ BLI_thread_lock(LOCK_MOVIECLIP);
BLI_make_existing_file(name);
if (IMB_saveiff(scaleibuf, name, IB_rect) == 0)
perror(name);
- BLI_unlock_thread(LOCK_MOVIECLIP);
+ BLI_thread_unlock(LOCK_MOVIECLIP);
IMB_freeImBuf(scaleibuf);
}
@@ -1560,9 +1577,9 @@ ImBuf *BKE_movieclip_anim_ibuf_for_frame(MovieClip *clip, MovieClipUser *user)
ImBuf *ibuf = NULL;
if (clip->source == MCLIP_SRC_MOVIE) {
- BLI_lock_thread(LOCK_MOVIECLIP);
+ BLI_thread_lock(LOCK_MOVIECLIP);
ibuf = movieclip_load_movie_file(clip, user, user->framenr, clip->flag);
- BLI_unlock_thread(LOCK_MOVIECLIP);
+ BLI_thread_unlock(LOCK_MOVIECLIP);
}
return ibuf;
@@ -1572,9 +1589,9 @@ bool BKE_movieclip_has_cached_frame(MovieClip *clip, MovieClipUser *user)
{
bool has_frame = false;
- BLI_lock_thread(LOCK_MOVIECLIP);
+ BLI_thread_lock(LOCK_MOVIECLIP);
has_frame = has_imbuf_cache(clip, user, clip->flag);
- BLI_unlock_thread(LOCK_MOVIECLIP);
+ BLI_thread_unlock(LOCK_MOVIECLIP);
return has_frame;
}
@@ -1585,15 +1602,15 @@ bool BKE_movieclip_put_frame_if_possible(MovieClip *clip,
{
bool result;
- BLI_lock_thread(LOCK_MOVIECLIP);
+ BLI_thread_lock(LOCK_MOVIECLIP);
result = put_imbuf_cache(clip, user, ibuf, clip->flag, false);
- BLI_unlock_thread(LOCK_MOVIECLIP);
+ BLI_thread_unlock(LOCK_MOVIECLIP);
return result;
}
void BKE_movieclip_eval_update(struct EvaluationContext *UNUSED(eval_ctx), MovieClip *clip)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, clip->id.name, clip);
+ DEG_debug_print_eval(__func__, clip->id.name, clip);
BKE_tracking_dopesheet_tag_update(&clip->tracking);
}
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index cbb7a766dfe..777c2a580fd 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -75,7 +75,7 @@
/* Remove the given NLA strip from the NLA track it occupies, free the strip's data,
* and the strip itself.
*/
-void free_nlastrip(ListBase *strips, NlaStrip *strip)
+void BKE_nlastrip_free(ListBase *strips, NlaStrip *strip)
{
NlaStrip *cs, *csn;
@@ -86,7 +86,7 @@ void free_nlastrip(ListBase *strips, NlaStrip *strip)
/* free child-strips */
for (cs = strip->strips.first; cs; cs = csn) {
csn = cs->next;
- free_nlastrip(&strip->strips, cs);
+ BKE_nlastrip_free(&strip->strips, cs);
}
/* remove reference to action */
@@ -113,7 +113,7 @@ void free_nlastrip(ListBase *strips, NlaStrip *strip)
/* Remove the given NLA track from the set of NLA tracks, free the track's data,
* and the track itself.
*/
-void free_nlatrack(ListBase *tracks, NlaTrack *nlt)
+void BKE_nlatrack_free(ListBase *tracks, NlaTrack *nlt)
{
NlaStrip *strip, *stripn;
@@ -124,7 +124,7 @@ void free_nlatrack(ListBase *tracks, NlaTrack *nlt)
/* free strips */
for (strip = nlt->strips.first; strip; strip = stripn) {
stripn = strip->next;
- free_nlastrip(&nlt->strips, strip);
+ BKE_nlastrip_free(&nlt->strips, strip);
}
/* free NLA track itself now */
@@ -137,7 +137,7 @@ void free_nlatrack(ListBase *tracks, NlaTrack *nlt)
/* Free the elements of type NLA Tracks provided in the given list, but do not free
* the list itself since that is not free-standing
*/
-void free_nladata(ListBase *tracks)
+void BKE_nla_tracks_free(ListBase *tracks)
{
NlaTrack *nlt, *nltn;
@@ -148,7 +148,7 @@ void free_nladata(ListBase *tracks)
/* free tracks one by one */
for (nlt = tracks->first; nlt; nlt = nltn) {
nltn = nlt->next;
- free_nlatrack(tracks, nlt);
+ BKE_nlatrack_free(tracks, nlt);
}
/* clear the list's pointers to be safe */
@@ -162,7 +162,7 @@ void free_nladata(ListBase *tracks)
*
* \param use_same_action When true, the existing action is used (instead of being duplicated)
*/
-NlaStrip *copy_nlastrip(NlaStrip *strip, const bool use_same_action)
+NlaStrip *BKE_nlastrip_copy(NlaStrip *strip, const bool use_same_action)
{
NlaStrip *strip_d;
NlaStrip *cs, *cs_d;
@@ -195,7 +195,7 @@ NlaStrip *copy_nlastrip(NlaStrip *strip, const bool use_same_action)
BLI_listbase_clear(&strip_d->strips);
for (cs = strip->strips.first; cs; cs = cs->next) {
- cs_d = copy_nlastrip(cs, use_same_action);
+ cs_d = BKE_nlastrip_copy(cs, use_same_action);
BLI_addtail(&strip_d->strips, cs_d);
}
@@ -204,7 +204,7 @@ NlaStrip *copy_nlastrip(NlaStrip *strip, const bool use_same_action)
}
/* Copy NLA Track */
-NlaTrack *copy_nlatrack(NlaTrack *nlt, const bool use_same_actions)
+NlaTrack *BKE_nlatrack_copy(NlaTrack *nlt, const bool use_same_actions)
{
NlaStrip *strip, *strip_d;
NlaTrack *nlt_d;
@@ -221,7 +221,7 @@ NlaTrack *copy_nlatrack(NlaTrack *nlt, const bool use_same_actions)
BLI_listbase_clear(&nlt_d->strips);
for (strip = nlt->strips.first; strip; strip = strip->next) {
- strip_d = copy_nlastrip(strip, use_same_actions);
+ strip_d = BKE_nlastrip_copy(strip, use_same_actions);
BLI_addtail(&nlt_d->strips, strip_d);
}
@@ -230,7 +230,7 @@ NlaTrack *copy_nlatrack(NlaTrack *nlt, const bool use_same_actions)
}
/* Copy all NLA data */
-void copy_nladata(ListBase *dst, ListBase *src)
+void BKE_nla_tracks_copy(ListBase *dst, ListBase *src)
{
NlaTrack *nlt, *nlt_d;
@@ -245,7 +245,7 @@ void copy_nladata(ListBase *dst, ListBase *src)
for (nlt = src->first; nlt; nlt = nlt->next) {
/* make a copy, and add the copy to the destination list */
// XXX: we need to fix this sometime
- nlt_d = copy_nlatrack(nlt, true);
+ nlt_d = BKE_nlatrack_copy(nlt, true);
BLI_addtail(dst, nlt_d);
}
}
@@ -255,7 +255,7 @@ void copy_nladata(ListBase *dst, ListBase *src)
/* Add a NLA Track to the given AnimData
* - prev: NLA-Track to add the new one after
*/
-NlaTrack *add_nlatrack(AnimData *adt, NlaTrack *prev)
+NlaTrack *BKE_nlatrack_add(AnimData *adt, NlaTrack *prev)
{
NlaTrack *nlt;
@@ -285,8 +285,8 @@ NlaTrack *add_nlatrack(AnimData *adt, NlaTrack *prev)
return nlt;
}
-/* Add a NLA Strip referencing the given Action */
-NlaStrip *add_nlastrip(bAction *act)
+/* Create a NLA Strip referencing the given Action */
+NlaStrip *BKE_nlastrip_new(bAction *act)
{
NlaStrip *strip;
@@ -327,7 +327,7 @@ NlaStrip *add_nlastrip(bAction *act)
}
/* Add new NLA-strip to the top of the NLA stack - i.e. into the last track if space, or a new one otherwise */
-NlaStrip *add_nlastrip_to_stack(AnimData *adt, bAction *act)
+NlaStrip *BKE_nlastack_add_strip(AnimData *adt, bAction *act)
{
NlaStrip *strip;
NlaTrack *nlt;
@@ -337,7 +337,7 @@ NlaStrip *add_nlastrip_to_stack(AnimData *adt, bAction *act)
return NULL;
/* create a new NLA strip */
- strip = add_nlastrip(act);
+ strip = BKE_nlastrip_new(act);
if (strip == NULL)
return NULL;
@@ -346,7 +346,7 @@ NlaStrip *add_nlastrip_to_stack(AnimData *adt, bAction *act)
/* trying to add to the last track failed (no track or no space),
* so add a new track to the stack, and add to that...
*/
- nlt = add_nlatrack(adt, NULL);
+ nlt = BKE_nlatrack_add(adt, NULL);
BKE_nlatrack_add_strip(nlt, strip);
}
@@ -358,7 +358,7 @@ NlaStrip *add_nlastrip_to_stack(AnimData *adt, bAction *act)
}
/* Add a NLA Strip referencing the given speaker's sound */
-NlaStrip *add_nla_soundstrip(Scene *scene, Speaker *speaker)
+NlaStrip *BKE_nla_add_soundstrip(Scene *scene, Speaker *speaker)
{
NlaStrip *strip = MEM_callocN(sizeof(NlaStrip), "NlaSoundStrip");
@@ -751,7 +751,7 @@ void BKE_nlastrips_clear_metastrip(ListBase *strips, NlaStrip *strip)
}
/* free the meta-strip now */
- free_nlastrip(strips, strip);
+ BKE_nlastrip_free(strips, strip);
}
/* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips
@@ -1392,7 +1392,12 @@ void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
/* store path - make copy, and store that */
fcu->rna_path = BLI_strdupn("influence", 9);
- /* TODO: insert a few keyframes to ensure default behavior? */
+ /* insert keyframe to ensure current value stays on first refresh */
+ fcu->bezt = MEM_callocN(sizeof(BezTriple), "nlastrip influence bezt");
+ fcu->totvert = 1;
+
+ fcu->bezt->vec[1][0] = strip->start;
+ fcu->bezt->vec[1][1] = strip->influence;
}
}
@@ -1709,7 +1714,7 @@ bool BKE_nla_action_stash(AnimData *adt)
}
}
- nlt = add_nlatrack(adt, prev_track);
+ nlt = BKE_nlatrack_add(adt, prev_track);
BLI_assert(nlt != NULL);
/* we need to ensure that if there wasn't any previous instance, it must go to tbe bottom of the stack */
@@ -1724,7 +1729,7 @@ bool BKE_nla_action_stash(AnimData *adt)
/* add the action as a strip in this new track
* NOTE: a new user is created here
*/
- strip = add_nlastrip(adt->action);
+ strip = BKE_nlastrip_new(adt->action);
BLI_assert(strip != NULL);
BKE_nlatrack_add_strip(nlt, strip);
@@ -1760,7 +1765,8 @@ bool BKE_nla_action_stash(AnimData *adt)
void BKE_nla_action_pushdown(AnimData *adt)
{
NlaStrip *strip;
-
+ const bool is_first = (adt) && (adt->nla_tracks.first == NULL);
+
/* sanity checks */
/* TODO: need to report the error for this */
if (ELEM(NULL, adt, adt->action))
@@ -1776,7 +1782,7 @@ void BKE_nla_action_pushdown(AnimData *adt)
}
/* add a new NLA strip to the track, which references the active action */
- strip = add_nlastrip_to_stack(adt, adt->action);
+ strip = BKE_nlastack_add_strip(adt, adt->action);
/* do other necessary work on strip */
if (strip) {
@@ -1784,6 +1790,32 @@ void BKE_nla_action_pushdown(AnimData *adt)
id_us_min(&adt->action->id);
adt->action = NULL;
+ /* copy current "action blending" settings from adt to the strip,
+ * as it was keyframed with these settings, so omitting them will
+ * change the effect [T54233]
+ *
+ * NOTE: We only do this when there are no tracks
+ */
+ if (is_first == false) {
+ strip->blendmode = adt->act_blendmode;
+ strip->influence = adt->act_influence;
+ strip->extendmode = adt->act_extendmode;
+
+ if (adt->act_influence < 1.0f) {
+ /* enable "user-controlled" influence (which will insert a default keyframe)
+ * so that the influence doesn't get lost on the new update
+ *
+ * NOTE: An alternative way would have been to instead hack the influence
+ * to not get always get reset to full strength if NLASTRIP_FLAG_USR_INFLUENCE
+ * is disabled but auto-blending isn't being used. However, that approach
+ * is a bit hacky/hard to discover, and may cause backwards compatability issues,
+ * so it's better to just do it this way.
+ */
+ strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
+ BKE_nlastrip_validate_fcurves(strip);
+ }
+ }
+
/* if the strip is the first one in the track it lives in, check if there
* are strips in any other tracks that may be before this, and set the extend
* mode accordingly
@@ -1793,7 +1825,8 @@ void BKE_nla_action_pushdown(AnimData *adt)
* so that it doesn't override strips in previous tracks
*/
/* FIXME: this needs to be more automated, since user can rearrange strips */
- strip->extendmode = NLASTRIP_EXTEND_HOLD_FORWARD;
+ if (strip->extendmode == NLASTRIP_EXTEND_HOLD)
+ strip->extendmode = NLASTRIP_EXTEND_HOLD_FORWARD;
}
/* make strip the active one... */
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index cac2aab26dd..41b7cd1f48e 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -75,6 +75,8 @@
#include "NOD_shader.h"
#include "NOD_texture.h"
+#include "DEG_depsgraph.h"
+
#define NODE_DEFAULT_MAX_WIDTH 700
/* Fallback types for undefined tree, nodes, sockets */
@@ -2787,7 +2789,7 @@ int BKE_node_instance_hash_haskey(bNodeInstanceHash *hash, bNodeInstanceKey key)
int BKE_node_instance_hash_size(bNodeInstanceHash *hash)
{
- return BLI_ghash_size(hash->ghash);
+ return BLI_ghash_len(hash->ghash);
}
void BKE_node_instance_hash_clear_tags(bNodeInstanceHash *hash)
@@ -3590,6 +3592,7 @@ static void registerShaderNodes(void)
register_node_type_sh_attribute();
register_node_type_sh_bevel();
register_node_type_sh_displacement();
+ register_node_type_sh_vector_displacement();
register_node_type_sh_geometry();
register_node_type_sh_light_path();
register_node_type_sh_light_falloff();
@@ -3615,6 +3618,7 @@ static void registerShaderNodes(void)
register_node_type_sh_holdout();
register_node_type_sh_volume_absorption();
register_node_type_sh_volume_scatter();
+ register_node_type_sh_volume_principled();
register_node_type_sh_subsurface_scattering();
register_node_type_sh_mix_shader();
register_node_type_sh_add_shader();
@@ -3819,6 +3823,7 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
void BKE_nodetree_remove_layer_n(bNodeTree *ntree, Scene *scene, const int layer_index)
{
+ BLI_assert(layer_index != -1);
for (bNode *node = ntree->nodes.first; node; node = node->next) {
if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) {
if (node->custom1 == layer_index) {
@@ -3868,8 +3873,6 @@ void BKE_nodetree_shading_params_eval(const struct EvaluationContext *UNUSED(eva
bNodeTree *ntree_dst,
const bNodeTree *ntree_src)
{
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s (%p)\n", __func__, ntree_src->id.name, ntree_dst);
- }
+ DEG_debug_print_eval(__func__, ntree_src->id.name, ntree_dst);
BKE_nodetree_copy_default_values(ntree_dst, ntree_src);
}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 2a4914da101..2cb4356a52a 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -200,12 +200,12 @@ void BKE_object_free_curve_cache(Object *ob)
}
}
-void BKE_object_free_modifiers(Object *ob)
+void BKE_object_free_modifiers(Object *ob, const int flag)
{
ModifierData *md;
while ((md = BLI_pophead(&ob->modifiers))) {
- modifier_free(md);
+ modifier_free_ex(md, flag);
}
/* particle modifiers were freed, so free the particlesystems as well */
@@ -240,7 +240,7 @@ void BKE_object_modifier_hook_reset(Object *ob, HookModifierData *hmd)
}
}
-bool BKE_object_support_modifier_type_check(Object *ob, int modifier_type)
+bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type)
{
const ModifierTypeInfo *mti;
@@ -267,7 +267,7 @@ bool BKE_object_support_modifier_type_check(Object *ob, int modifier_type)
void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_src)
{
ModifierData *md;
- BKE_object_free_modifiers(ob_dst);
+ BKE_object_free_modifiers(ob_dst, 0);
if (!ELEM(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
/* only objects listed above can have modifiers and linking them to objects
@@ -427,7 +427,8 @@ void BKE_object_free(Object *ob)
{
BKE_animdata_free((ID *)ob, false);
- BKE_object_free_modifiers(ob);
+ /* BKE_<id>_free shall never touch to ID->us. Never ever. */
+ BKE_object_free_modifiers(ob, LIB_ID_CREATE_NO_USER_REFCOUNT);
MEM_SAFE_FREE(ob->mat);
MEM_SAFE_FREE(ob->matbits);
@@ -467,11 +468,8 @@ void BKE_object_free(Object *ob)
GPU_lamp_free(ob);
for (ObjectEngineData *oed = ob->drawdata.first; oed; oed = oed->next) {
- if (oed->storage) {
- if (oed->free) {
- oed->free(oed->storage);
- }
- MEM_freeN(oed->storage);
+ if (oed->free != NULL) {
+ oed->free(oed);
}
}
BLI_freelistN(&ob->drawdata);
@@ -498,7 +496,7 @@ void BKE_object_free(Object *ob)
}
/* actual check for internal data, not context or flags */
-bool BKE_object_is_in_editmode(Object *ob)
+bool BKE_object_is_in_editmode(const Object *ob)
{
if (ob->data == NULL)
return false;
@@ -546,13 +544,13 @@ bool BKE_object_is_in_editmode(Object *ob)
return false;
}
-bool BKE_object_is_in_editmode_vgroup(Object *ob)
+bool BKE_object_is_in_editmode_vgroup(const Object *ob)
{
return (OB_TYPE_SUPPORT_VGROUP(ob->type) &&
BKE_object_is_in_editmode(ob));
}
-bool BKE_object_is_in_wpaint_select_vert(Object *ob)
+bool BKE_object_is_in_wpaint_select_vert(const Object *ob)
{
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
@@ -594,7 +592,7 @@ bool BKE_object_is_visible(Object *ob, const eObjectVisibilityCheck mode)
}
}
-bool BKE_object_exists_check(Object *obtest)
+bool BKE_object_exists_check(const Object *obtest)
{
Object *ob;
@@ -1056,7 +1054,6 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int f
BLI_listbase_clear(&psysn->pathcachebufs);
BLI_listbase_clear(&psysn->childcachebufs);
- psysn->renderdata = NULL;
/* XXX Never copy caches here? */
psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, flag & ~LIB_ID_COPY_CACHES);
@@ -1169,7 +1166,7 @@ static void copy_object_lod(Object *obn, const Object *ob, const int UNUSED(flag
obn->currentlod = (LodLevel *)obn->lodlevels.first;
}
-bool BKE_object_pose_context_check(Object *ob)
+bool BKE_object_pose_context_check(const Object *ob)
{
if ((ob) &&
(ob->type == OB_ARMATURE) &&
@@ -1193,12 +1190,26 @@ Object *BKE_object_pose_armature_get(Object *ob)
ob = modifiers_isDeformedByArmature(ob);
+ /* Only use selected check when non-active. */
if (BKE_object_pose_context_check(ob))
return ob;
return NULL;
}
+Object *BKE_object_pose_armature_get_visible(Object *ob, ViewLayer *view_layer)
+{
+ Object *ob_armature = BKE_object_pose_armature_get(ob);
+ if (ob_armature) {
+ Base *base = BKE_view_layer_base_find(view_layer, ob_armature);
+ if (base) {
+ if (BASE_VISIBLE(base)) {
+ return ob_armature;
+ }
+ }
+ }
+ return NULL;
+}
void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
{
copy_v3_v3(ob_tar->loc, ob_src->loc);
@@ -1357,13 +1368,13 @@ void BKE_object_make_local(Main *bmain, Object *ob, const bool lib_local)
}
/* Returns true if the Object is from an external blend file (libdata) */
-bool BKE_object_is_libdata(Object *ob)
+bool BKE_object_is_libdata(const Object *ob)
{
return (ob && ID_IS_LINKED(ob));
}
/* Returns true if the Object data is from an external blend file (libdata) */
-bool BKE_object_obdata_is_libdata(Object *ob)
+bool BKE_object_obdata_is_libdata(const Object *ob)
{
/* Linked objects with local obdata are forbidden! */
BLI_assert(!ob || !ob->data || (ID_IS_LINKED(ob) ? ID_IS_LINKED(ob->data) : true));
@@ -2318,7 +2329,7 @@ void BKE_object_apply_mat4(Object *ob, float mat[4][4], const bool use_compat, c
BoundBox *BKE_boundbox_alloc_unit(void)
{
BoundBox *bb;
- const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {-1.0f, -1.0f, -1.0f};
+ const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f};
bb = MEM_callocN(sizeof(BoundBox), "OB-BoundBox");
BKE_boundbox_init_from_minmax(bb, min, max);
@@ -2767,7 +2778,7 @@ void BKE_object_handle_update_ex(const EvaluationContext *eval_ctx,
* which is only in BKE_object_where_is_calc now */
/* XXX: should this case be OB_RECALC_OB instead? */
if (recalc_object || recalc_data) {
- if (G.debug & G_DEBUG_DEPSGRAPH) {
+ if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) {
printf("recalcob %s\n", ob->id.name + 2);
}
/* Handle proxy copy for target. */
@@ -3143,7 +3154,7 @@ bool BKE_object_flag_test_recursive(const Object *ob, short flag)
}
}
-bool BKE_object_is_child_recursive(Object *ob_parent, Object *ob_child)
+bool BKE_object_is_child_recursive(const Object *ob_parent, const Object *ob_child)
{
for (ob_child = ob_child->parent; ob_child; ob_child = ob_child->parent) {
if (ob_child == ob_parent) {
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index 754434eaef6..fb2e824b299 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -42,7 +42,7 @@
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
@@ -460,6 +460,70 @@ void BKE_object_defgroup_remove_all(struct Object *ob)
BKE_object_defgroup_remove_all_ex(ob, false);
}
+/**
+ * Compute mapping for vertex groups with matching name, -1 is used for no remapping.
+ * Returns null if no remapping is required.
+ * The returned array has to be freed.
+ */
+int *BKE_object_defgroup_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len)
+{
+ /* Build src to merged mapping of vgroup indices. */
+ if (BLI_listbase_is_empty(&ob_src->defbase) || BLI_listbase_is_empty(&ob_dst->defbase)) {
+ *r_map_len = 0;
+ return NULL;
+ }
+
+ bDeformGroup *dg_src;
+ *r_map_len = BLI_listbase_count(&ob_src->defbase);
+ int *vgroup_index_map = MEM_malloc_arrayN(*r_map_len, sizeof(*vgroup_index_map), "defgroup index map create");
+ bool is_vgroup_remap_needed = false;
+ int i;
+
+ for (dg_src = ob_src->defbase.first, i = 0; dg_src; dg_src = dg_src->next, i++) {
+ vgroup_index_map[i] = defgroup_name_index(ob_dst, dg_src->name);
+ is_vgroup_remap_needed = is_vgroup_remap_needed || (vgroup_index_map[i] != i);
+ }
+
+ if (!is_vgroup_remap_needed) {
+ MEM_freeN(vgroup_index_map);
+ vgroup_index_map = NULL;
+ *r_map_len = 0;
+ }
+
+ return vgroup_index_map;
+}
+
+void BKE_object_defgroup_index_map_apply(MDeformVert *dvert, int dvert_len, const int *map, int map_len)
+{
+ if (map == NULL || map_len == 0) {
+ return;
+ }
+
+ MDeformVert *dv = dvert;
+ for (int i = 0; i < dvert_len; i++, dv++) {
+ int totweight = dv->totweight;
+ for (int j = 0; j < totweight; j++) {
+ int def_nr = dv->dw[j].def_nr;
+ if ((uint)def_nr < (uint)map_len && map[def_nr] != -1) {
+ dv->dw[j].def_nr = map[def_nr];
+ }
+ else {
+ totweight--;
+ dv->dw[j] = dv->dw[totweight];
+ j--;
+ }
+ }
+ if (totweight != dv->totweight) {
+ if (totweight) {
+ dv->dw = MEM_reallocN(dv->dw, sizeof(*dv->dw) * totweight);
+ }
+ else {
+ MEM_SAFE_FREE(dv->dw);
+ }
+ dv->totweight = totweight;
+ }
+ }
+}
/**
* Get MDeformVert vgroup data from given object. Should only be used in Object mode.
@@ -542,7 +606,7 @@ bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot)
BLI_ghash_insert(gh, dg->name, NULL);
}
- BLI_assert(BLI_ghash_size(gh) == defbase_tot);
+ BLI_assert(BLI_ghash_len(gh) == defbase_tot);
/* now loop through the armature modifiers and identify deform bones */
for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0), modifiers_getVirtualModifierList(ob, &virtualModifierData) : md->next) {
@@ -577,7 +641,7 @@ bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot)
defgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL);
}
- BLI_assert(i == BLI_ghash_size(gh));
+ BLI_assert(i == BLI_ghash_len(gh));
BLI_ghash_free(gh, NULL, NULL);
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index 13589866e48..1b976fef166 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -74,6 +74,7 @@ typedef struct DupliContext {
bool do_update;
bool animated;
Group *group; /* XXX child objects are selected from this group if set, could be nicer */
+ Object *obedit; /* Only to check if the object is in edit-mode. */
Scene *scene;
ViewLayer *view_layer;
@@ -108,6 +109,7 @@ static void init_context(DupliContext *r_ctx, const EvaluationContext *eval_ctx,
r_ctx->group = NULL;
r_ctx->object = ob;
+ r_ctx->obedit = OBEDIT_FROM_OBACT(ob);
if (space_mat)
copy_m4_m4(r_ctx->space_mat, space_mat);
else
@@ -241,14 +243,13 @@ static bool is_child(const Object *ob, const Object *parent)
static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChildDuplisFunc make_child_duplis_cb)
{
Object *parent = ctx->object;
- Object *obedit = ctx->scene->obedit;
if (ctx->group) {
int groupid = 0;
- FOREACH_GROUP_BASE(ctx->group, base)
+ FOREACH_GROUP_BASE_BEGIN(ctx->group, base)
{
Object *ob = base->object;
- if ((base->flag & BASE_VISIBLED) && ob != obedit && is_child(ob, parent)) {
+ if ((base->flag & BASE_VISIBLED) && ob != ctx->obedit && is_child(ob, parent)) {
DupliContext pctx;
copy_dupli_context(&pctx, ctx, ctx->object, NULL, groupid, false);
@@ -267,7 +268,7 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
ViewLayer *view_layer = ctx->view_layer;
for (Base *base = view_layer->object_bases.first; base; base = base->next, baseid++) {
Object *ob = base->object;
- if ((base->flag & BASE_VISIBLED) && ob != obedit && is_child(ob, parent)) {
+ if ((ob != ctx->obedit) && is_child(ob, parent)) {
DupliContext pctx;
copy_dupli_context(&pctx, ctx, ctx->object, NULL, baseid, false);
@@ -880,7 +881,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
BLI_srandom((unsigned int)(31415926 + psys->seed));
- if ((psys->renderdata || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
+ if ((for_render || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
ParticleSimulationData sim = {NULL};
sim.eval_ctx = ctx->eval_ctx;
sim.scene = scene;
@@ -931,12 +932,12 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
totgroup += dw->count;
}
else {
- FOREACH_GROUP_OBJECT(part->dup_group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
{
(void) object;
totgroup++;
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
/* we also copy the actual objects to restore afterwards, since
@@ -956,7 +957,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
}
else {
a = 0;
- FOREACH_GROUP_OBJECT(part->dup_group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
{
oblist[a] = object;
obcopylist[a] = *object;
@@ -966,7 +967,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
continue;
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
}
else {
@@ -1056,7 +1057,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
if (part->ren_as == PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
b = 0;
- FOREACH_GROUP_OBJECT(part->dup_group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
{
copy_m4_m4(tmat, oblist[b]->obmat);
@@ -1081,7 +1082,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
b++;
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
else {
/* to give ipos in object correct offset */
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 99291b14b88..10ccc9fb672 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -66,12 +66,11 @@
#include "MEM_guardedalloc.h"
#include "DEG_depsgraph.h"
-#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
void BKE_object_eval_local_transform(const EvaluationContext *UNUSED(eval_ctx),
Object *ob)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
/* calculate local matrix */
BKE_object_to_mat4(ob, ob->obmat);
@@ -89,7 +88,7 @@ void BKE_object_eval_parent(const EvaluationContext *UNUSED(eval_ctx),
float tmat[4][4];
float locmat[4][4];
- DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
/* get local matrix (but don't calculate it, as that was done already!) */
// XXX: redundant?
@@ -118,7 +117,7 @@ void BKE_object_eval_constraints(const EvaluationContext *eval_ctx,
bConstraintOb *cob;
float ctime = BKE_scene_frame_get(scene);
- DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
/* evaluate constraints stack */
/* TODO: split this into:
@@ -136,7 +135,7 @@ void BKE_object_eval_constraints(const EvaluationContext *eval_ctx,
void BKE_object_eval_done(const EvaluationContext *UNUSED(eval_ctx), Object *ob)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
/* Set negative scale flag in object. */
if (is_negative_m4(ob->obmat)) ob->transflag |= OB_NEG_SCALE;
@@ -153,7 +152,7 @@ void BKE_object_handle_data_update(
Key *key;
float ctime = BKE_scene_frame_get(scene);
- if (G.debug & G_DEBUG_DEPSGRAPH)
+ if (G.debug & G_DEBUG_DEPSGRAPH_EVAL)
printf("recalcdata %s\n", ob->id.name + 2);
/* TODO(sergey): Only used by legacy depsgraph. */
@@ -174,7 +173,7 @@ void BKE_object_handle_data_update(
switch (ob->type) {
case OB_MESH:
{
- BMEditMesh *em = (ob == scene->obedit) ? BKE_editmesh_from_object(ob) : NULL;
+ BMEditMesh *em = (ob->mode & OB_MODE_EDIT) ? BKE_editmesh_from_object(ob) : NULL;
uint64_t data_mask = scene->customdata_mask | CD_MASK_BAREMESH;
#ifdef WITH_FREESTYLE
/* make sure Freestyle edge/face marks appear in DM for render (see T40315) */
@@ -224,7 +223,7 @@ void BKE_object_handle_data_update(
}
/* particles */
- if (ob != scene->obedit && ob->particlesystem.first) {
+ if (!(ob->mode & OB_MODE_EDIT) && ob->particlesystem.first) {
ParticleSystem *tpsys, *psys;
DerivedMesh *dm;
ob->transflag &= ~OB_DUPLIPARTS;
@@ -306,7 +305,7 @@ void BKE_object_eval_uber_data(const EvaluationContext *eval_ctx,
Scene *scene,
Object *ob)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
BLI_assert(ob->type != OB_ARMATURE);
BKE_object_handle_data_update(eval_ctx, scene, ob);
@@ -387,7 +386,7 @@ void BKE_object_eval_cloth(const EvaluationContext *UNUSED(eval_ctx),
Scene *scene,
Object *object)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object);
+ DEG_debug_print_eval(__func__, object->id.name, object);
BKE_ptcache_object_reset(scene, object, PTCACHE_RESET_DEPSGRAPH);
}
@@ -410,7 +409,7 @@ void BKE_object_eval_transform_all(const EvaluationContext *eval_ctx,
void BKE_object_eval_update_shading(const EvaluationContext *UNUSED(eval_ctx),
Object *object)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object);
+ DEG_debug_print_eval(__func__, object->id.name, object);
if (object->type == OB_MESH) {
BKE_mesh_batch_cache_dirty(object->data, BKE_MESH_BATCH_DIRTY_SHADING);
}
@@ -419,7 +418,7 @@ void BKE_object_eval_update_shading(const EvaluationContext *UNUSED(eval_ctx),
void BKE_object_data_select_update(const EvaluationContext *UNUSED(eval_ctx),
struct ID *object_data)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, object_data->name, object_data);
+ DEG_debug_print_eval(__func__, object_data->name, object_data);
switch (GS(object_data->name)) {
case ID_ME:
BKE_mesh_batch_cache_dirty((Mesh *)object_data,
@@ -442,10 +441,17 @@ void BKE_object_data_select_update(const EvaluationContext *UNUSED(eval_ctx),
}
}
-void BKE_object_eval_flush_base_flags(const EvaluationContext *UNUSED(eval_ctx),
- Object *object, Base *base, bool is_from_set)
+void BKE_object_eval_flush_base_flags(const EvaluationContext *eval_ctx,
+ Object *object, int base_index, bool is_from_set)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object);
+ ViewLayer *view_layer = eval_ctx->view_layer;
+ BLI_assert(view_layer->object_bases_array != NULL);
+ BLI_assert(base_index >= 0);
+ BLI_assert(base_index < MEM_allocN_len(view_layer->object_bases_array) / sizeof(Base *));
+ Base *base = view_layer->object_bases_array[base_index];
+ BLI_assert(base->object == object);
+
+ DEG_debug_print_eval(__func__, object->id.name, object);
/* Make sure we have the base collection settings is already populated.
* This will fail when BKE_layer_eval_layer_collection_pre hasn't run yet.
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 0b4bc39627e..2d8527f23d6 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -917,7 +917,7 @@ void BKE_ocean_init(struct Ocean *o, int M, int N, float Lx, float Lz, float V,
o->_fft_in = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in");
o->_htilda = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_htilda");
- BLI_lock_thread(LOCK_FFTW);
+ BLI_thread_lock(LOCK_FFTW);
if (o->_do_disp_y) {
o->_disp_y = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_y");
@@ -963,7 +963,7 @@ void BKE_ocean_init(struct Ocean *o, int M, int N, float Lx, float Lz, float V,
o->_Jxz_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jxz, o->_Jxz, FFTW_ESTIMATE);
}
- BLI_unlock_thread(LOCK_FFTW);
+ BLI_thread_unlock(LOCK_FFTW);
BLI_rw_mutex_unlock(&o->oceanmutex);
@@ -978,7 +978,7 @@ void BKE_ocean_free_data(struct Ocean *oc)
BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_WRITE);
- BLI_lock_thread(LOCK_FFTW);
+ BLI_thread_lock(LOCK_FFTW);
if (oc->_do_disp_y) {
fftw_destroy_plan(oc->_disp_y_plan);
@@ -1016,7 +1016,7 @@ void BKE_ocean_free_data(struct Ocean *oc)
MEM_freeN(oc->_Jxz);
}
- BLI_unlock_thread(LOCK_FFTW);
+ BLI_thread_unlock(LOCK_FFTW);
if (oc->_fft_in)
MEM_freeN(oc->_fft_in);
diff --git a/source/blender/blenkernel/intern/outliner_treehash.c b/source/blender/blenkernel/intern/outliner_treehash.c
index d9a602aa41e..9bbde607b80 100644
--- a/source/blender/blenkernel/intern/outliner_treehash.c
+++ b/source/blender/blenkernel/intern/outliner_treehash.c
@@ -133,7 +133,7 @@ static void fill_treehash(void *treehash, BLI_mempool *treestore)
void *BKE_outliner_treehash_create_from_treestore(BLI_mempool *treestore)
{
- GHash *treehash = BLI_ghash_new_ex(tse_hash, tse_cmp, "treehash", BLI_mempool_count(treestore));
+ GHash *treehash = BLI_ghash_new_ex(tse_hash, tse_cmp, "treehash", BLI_mempool_len(treestore));
fill_treehash(treehash, treestore);
return treehash;
}
@@ -147,7 +147,7 @@ void *BKE_outliner_treehash_rebuild_from_treestore(void *treehash, BLI_mempool *
{
BLI_assert(treehash);
- BLI_ghash_clear_ex(treehash, NULL, free_treehash_group, BLI_mempool_count(treestore));
+ BLI_ghash_clear_ex(treehash, NULL, free_treehash_group, BLI_mempool_len(treestore));
fill_treehash(treehash, treestore);
return treehash;
}
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index 35e2531675d..f17c10765b8 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -354,16 +354,15 @@ int writePackedFile(ReportList *reports, const char *filename, PackedFile *pf, i
return (ret_value);
}
-
-/*
+
+/**
* This function compares a packed file to a 'real' file.
* It returns an integer indicating if:
*
- * PF_EQUAL - the packed file and original file are identical
- * PF_DIFFERENT - the packed file and original file differ
- * PF_NOFILE - the original file doens't exist
+ * - PF_EQUAL: the packed file and original file are identical
+ * - PF_DIFFERENT: the packed file and original file differ
+ * - PF_NOFILE: the original file doens't exist
*/
-
int checkPackedFile(const char *filename, PackedFile *pf)
{
BLI_stat_t st;
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 152a882de97..20375fe6953 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -41,6 +41,7 @@
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
#include "DNA_space_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_bitmap.h"
#include "BLI_utildefines.h"
@@ -176,6 +177,8 @@ Paint *BKE_paint_get_active(Scene *sce, ViewLayer *view_layer)
if (ts->use_uv_sculpt)
return &ts->uvsculpt->paint;
return &ts->imapaint.paint;
+ default:
+ break;
}
}
@@ -376,7 +379,7 @@ void BKE_paint_curve_clamp_endpoint_add_index(PaintCurve *pc, const int add_inde
/* remove colour from palette. Must be certain color is inside the palette! */
void BKE_palette_color_remove(Palette *palette, PaletteColor *color)
{
- if (BLI_listbase_count_ex(&palette->colors, palette->active_color) == palette->active_color) {
+ if (BLI_listbase_count_at_most(&palette->colors, palette->active_color) == palette->active_color) {
palette->active_color--;
}
@@ -499,7 +502,7 @@ void BKE_paint_cavity_curve_preset(Paint *p, int preset)
curvemapping_changed(p->cavity_curve, false);
}
-short BKE_paint_object_mode_from_paint_mode(ePaintMode mode)
+eObjectMode BKE_paint_object_mode_from_paint_mode(ePaintMode mode)
{
switch (mode) {
case ePaintSculpt:
@@ -529,7 +532,7 @@ void BKE_paint_init(Scene *sce, ePaintMode mode, const char col[3])
/* If there's no brush, create one */
brush = BKE_paint_brush(paint);
if (brush == NULL) {
- short ob_mode = BKE_paint_object_mode_from_paint_mode(mode);
+ eObjectMode ob_mode = BKE_paint_object_mode_from_paint_mode(mode);
brush = BKE_brush_first_search(G.main, ob_mode);
if (!brush) {
@@ -902,7 +905,7 @@ void BKE_sculpt_update_mesh_elements(
if (!CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK)) {
#if 1
BKE_sculpt_mask_layers_ensure(ob, mmd);
-#else /* if we wanted to support adding mask data while multi-res painting, we would need to do this */
+#else /* if we wanted to support adding mask data while multi-res painting, we would need to do this */
if ((ED_sculpt_mask_layers_ensure(ob, mmd) & ED_SCULPT_MASK_LAYER_CALC_LOOP)) {
/* remake the derived mesh */
ob->recalc |= OB_RECALC_DATA;
@@ -1064,3 +1067,39 @@ int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd)
return ret;
}
+
+void BKE_sculpt_toolsettings_data_ensure(struct Scene *scene)
+{
+ Sculpt *sd = scene->toolsettings->sculpt;
+ if (sd == NULL) {
+ sd = scene->toolsettings->sculpt = MEM_callocN(sizeof(Sculpt), __func__);
+
+ /* Turn on X plane mirror symmetry by default */
+ sd->paint.symmetry_flags |= PAINT_SYMM_X;
+ sd->paint.flags |= PAINT_SHOW_BRUSH;
+
+ /* Make sure at least dyntopo subdivision is enabled */
+ sd->flags |= SCULPT_DYNTOPO_SUBDIVIDE | SCULPT_DYNTOPO_COLLAPSE;
+ }
+
+ if (!sd->detail_size) {
+ sd->detail_size = 12;
+ }
+ if (!sd->detail_percent) {
+ sd->detail_percent = 25;
+ }
+ if (sd->constant_detail == 0.0f) {
+ sd->constant_detail = 3.0f;
+ }
+
+ /* Set sane default tiling offsets */
+ if (!sd->paint.tile_offset[0]) {
+ sd->paint.tile_offset[0] = 1.0f;
+ }
+ if (!sd->paint.tile_offset[1]) {
+ sd->paint.tile_offset[1] = 1.0f;
+ }
+ if (!sd->paint.tile_offset[2]) {
+ sd->paint.tile_offset[2] = 1.0f;
+ }
+}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index e23ca3eaa09..713d523cb1e 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -87,9 +87,12 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#include "RE_render_ext.h"
+#include "particle_private.h"
+
unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT];
unsigned int PSYS_FRAND_SEED_MULTIPLIER[PSYS_FRAND_COUNT];
float PSYS_FRAND_BASE[PSYS_FRAND_COUNT];
@@ -109,9 +112,6 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread
ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex);
static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSettings *part, ParticleData *par,
int child_index, int face_index, const float fw[4], float *orco, ParticleTexture *ptex, int event, float cfra);
-extern void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim,
- ParticleTexture *ptex, const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3],
- ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t);
/* few helpers for countall etc. */
int count_particles(ParticleSystem *psys)
@@ -252,7 +252,7 @@ struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData
{
struct LatticeDeformData *lattice_deform_data = NULL;
- if (psys_in_edit_mode(sim->eval_ctx->view_layer, sim->psys) == 0) {
+ if (psys_in_edit_mode(sim->eval_ctx->depsgraph, sim->psys) == 0) {
Object *lattice = NULL;
ModifierData *md = (ModifierData *)psys_get_modifier(sim->ob, sim->psys);
int mode = G.is_rendering ? eModifierMode_Render : eModifierMode_Realtime;
@@ -289,13 +289,16 @@ void psys_enable_all(Object *ob)
psys->flag &= ~PSYS_DISABLED;
}
-bool psys_in_edit_mode(ViewLayer *view_layer, ParticleSystem *psys)
+bool psys_in_edit_mode(Depsgraph *depsgraph, ParticleSystem *psys)
{
+ ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
+ const bool use_render_params = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
+
return (view_layer->basact &&
(view_layer->basact->object->mode & OB_MODE_PARTICLE_EDIT) &&
psys == psys_get_current((view_layer->basact)->object) &&
(psys->edit || psys->pointcache->edit) &&
- !psys->renderdata);
+ !use_render_params);
}
bool psys_check_enabled(Object *ob, ParticleSystem *psys, const bool use_render_params)
@@ -306,7 +309,7 @@ bool psys_check_enabled(Object *ob, ParticleSystem *psys, const bool use_render_
return 0;
psmd = psys_get_modifier(ob, psys);
- if (psys->renderdata || use_render_params) {
+ if (use_render_params) {
if (!(psmd->modifier.mode & eModifierMode_Render))
return 0;
}
@@ -351,7 +354,7 @@ void psys_check_group_weights(ParticleSettings *part)
}
/* then add objects in the group to new list */
- FOREACH_GROUP_OBJECT(part->dup_group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
{
dw = part->dupliweights.first;
while (dw && dw->ob != object) {
@@ -365,7 +368,7 @@ void psys_check_group_weights(ParticleSettings *part)
BLI_addtail(&part->dupliweights, dw);
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
dw = part->dupliweights.first;
for (; dw; dw = dw->next) {
@@ -413,6 +416,8 @@ void BKE_particlesettings_free(ParticleSettings *part)
curvemapping_free(part->clumpcurve);
if (part->roughcurve)
curvemapping_free(part->roughcurve);
+ if (part->twistcurve)
+ curvemapping_free(part->twistcurve);
free_partdeflect(part->pd);
free_partdeflect(part->pd2);
@@ -621,204 +626,6 @@ void psys_free(Object *ob, ParticleSystem *psys)
}
/************************************************/
-/* Rendering */
-/************************************************/
-/* these functions move away particle data and bring it back after
- * rendering, to make different render settings possible without
- * removing the previous data. this should be solved properly once */
-
-void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset)
-{
- ParticleRenderData *data;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
-
- if (psys->renderdata)
- return;
-
- data = MEM_callocN(sizeof(ParticleRenderData), "ParticleRenderData");
-
- data->child = psys->child;
- data->totchild = psys->totchild;
- data->pathcache = psys->pathcache;
- data->pathcachebufs.first = psys->pathcachebufs.first;
- data->pathcachebufs.last = psys->pathcachebufs.last;
- data->totcached = psys->totcached;
- data->childcache = psys->childcache;
- data->childcachebufs.first = psys->childcachebufs.first;
- data->childcachebufs.last = psys->childcachebufs.last;
- data->totchildcache = psys->totchildcache;
-
- if (psmd->dm_final) {
- data->dm = CDDM_copy_with_tessface(psmd->dm_final);
- }
- data->totdmvert = psmd->totdmvert;
- data->totdmedge = psmd->totdmedge;
- data->totdmface = psmd->totdmface;
-
- psys->child = NULL;
- psys->pathcache = NULL;
- psys->childcache = NULL;
- psys->totchild = psys->totcached = psys->totchildcache = 0;
- BLI_listbase_clear(&psys->pathcachebufs);
- BLI_listbase_clear(&psys->childcachebufs);
-
- copy_m4_m4(data->winmat, winmat);
- mul_m4_m4m4(data->viewmat, viewmat, ob->obmat);
- mul_m4_m4m4(data->mat, winmat, data->viewmat);
- data->winx = winx;
- data->winy = winy;
-
- data->timeoffset = timeoffset;
-
- psys->renderdata = data;
-
- /* Hair can and has to be recalculated if everything isn't displayed. */
- if (psys->part->disp != 100 && ELEM(psys->part->type, PART_HAIR, PART_FLUID)) {
- psys->recalc |= PSYS_RECALC_RESET;
- }
-}
-
-void psys_render_restore(Object *ob, ParticleSystem *psys)
-{
- ParticleRenderData *data;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- float render_disp = psys_get_current_display_percentage(psys);
- float disp;
-
- data = psys->renderdata;
- if (!data)
- return;
-
- if (data->elems)
- MEM_freeN(data->elems);
-
- if (psmd->dm_final) {
- psmd->dm_final->needsFree = 1;
- psmd->dm_final->release(psmd->dm_final);
- }
- if (psmd->dm_deformed) {
- psmd->dm_deformed->needsFree = 1;
- psmd->dm_deformed->release(psmd->dm_deformed);
- psmd->dm_deformed = NULL;
- }
-
- psys_free_path_cache(psys, NULL);
-
- if (psys->child) {
- MEM_freeN(psys->child);
- psys->child = 0;
- psys->totchild = 0;
- }
-
- psys->child = data->child;
- psys->totchild = data->totchild;
- psys->pathcache = data->pathcache;
- psys->pathcachebufs.first = data->pathcachebufs.first;
- psys->pathcachebufs.last = data->pathcachebufs.last;
- psys->totcached = data->totcached;
- psys->childcache = data->childcache;
- psys->childcachebufs.first = data->childcachebufs.first;
- psys->childcachebufs.last = data->childcachebufs.last;
- psys->totchildcache = data->totchildcache;
-
- psmd->dm_final = data->dm;
- psmd->totdmvert = data->totdmvert;
- psmd->totdmedge = data->totdmedge;
- psmd->totdmface = data->totdmface;
- psmd->flag &= ~eParticleSystemFlag_psys_updated;
-
- if (psmd->dm_final) {
- if (!psmd->dm_final->deformedOnly) {
- if (ob->derivedDeform) {
- psmd->dm_deformed = CDDM_copy(ob->derivedDeform);
- }
- else {
- psmd->dm_deformed = CDDM_from_mesh((Mesh *)ob->data);
- }
- DM_ensure_tessface(psmd->dm_deformed);
- }
- psys_calc_dmcache(ob, psmd->dm_final, psmd->dm_deformed, psys);
- }
-
- MEM_freeN(data);
- psys->renderdata = NULL;
-
- /* restore particle display percentage */
- disp = psys_get_current_display_percentage(psys);
-
- if (disp != render_disp) {
- /* Hair can and has to be recalculated if everything isn't displayed. */
- if (ELEM(psys->part->type, PART_HAIR, PART_FLUID)) {
- psys->recalc |= PSYS_RECALC_RESET;
- }
- else {
- PARTICLE_P;
-
- LOOP_PARTICLES {
- if (psys_frand(psys, p) > disp)
- pa->flag |= PARS_NO_DISP;
- else
- pa->flag &= ~PARS_NO_DISP;
- }
- }
- }
-}
-
-bool psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float *params)
-{
- ParticleRenderData *data;
- ParticleRenderElem *elem;
- float x, w, scale, alpha, lambda, t, scalemin, scalemax;
- int b;
-
- if (!(psys->renderdata && (psys->part->simplify_flag & PART_SIMPLIFY_ENABLE)))
- return false;
-
- data = psys->renderdata;
- if (!data->do_simplify)
- return false;
- b = (data->index_mf_to_mpoly) ? DM_origindex_mface_mpoly(data->index_mf_to_mpoly, data->index_mp_to_orig, cpa->num) : cpa->num;
- if (b == ORIGINDEX_NONE) {
- return false;
- }
-
- elem = &data->elems[b];
-
- lambda = elem->lambda;
- t = elem->t;
- scalemin = elem->scalemin;
- scalemax = elem->scalemax;
-
- if (!elem->reduce) {
- scale = scalemin;
- alpha = 1.0f;
- }
- else {
- x = (elem->curchild + 0.5f) / elem->totchild;
- if (x < lambda - t) {
- scale = scalemax;
- alpha = 1.0f;
- }
- else if (x >= lambda + t) {
- scale = scalemin;
- alpha = 0.0f;
- }
- else {
- w = (lambda + t - x) / (2.0f * t);
- scale = scalemin + (scalemax - scalemin) * w;
- alpha = w;
- }
- }
-
- params[0] = scale;
- params[1] = alpha;
-
- elem->curchild++;
-
- return 1;
-}
-
-/************************************************/
/* Interpolation */
/************************************************/
static float interpolate_particle_value(float v1, float v2, float v3, float v4, const float w[4], int four)
@@ -1811,11 +1618,6 @@ void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int in
/* Path Cache */
/************************************************/
-extern void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape, float amplitude, float flat,
- short type, short axis, float obmat[4][4], int smooth_start);
-extern float do_clump(ParticleKey *state, const float par_co[3], float time, const float orco_offset[3], float clumpfac, float clumppow, float pa_clump,
- bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve);
-
void precalc_guides(ParticleSimulationData *sim, ListBase *effectors)
{
EffectedPoint point;
@@ -2059,7 +1861,7 @@ void psys_find_parents(ParticleSimulationData *sim, const bool use_render_params
int from = PART_FROM_FACE;
totparent = (int)(totchild * part->parents * 0.3f);
- if ((sim->psys->renderdata || use_render_params) && part->child_nbr && part->ren_child_nbr)
+ if (use_render_params && part->child_nbr && part->ren_child_nbr)
totparent *= (float)part->child_nbr / (float)part->ren_child_nbr;
/* hard limit, workaround for it being ignored above */
@@ -2103,10 +1905,10 @@ static bool psys_thread_context_init_path(
psys_thread_context_init(ctx, sim);
/*---start figuring out what is actually wanted---*/
- if (psys_in_edit_mode(sim->eval_ctx->view_layer, psys)) {
+ if (psys_in_edit_mode(sim->eval_ctx->depsgraph, psys)) {
ParticleEditSettings *pset = &scene->toolsettings->particle;
- if ((psys->renderdata == 0 && use_render_params == 0) && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
+ if ((use_render_params == 0) && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
totchild = 0;
segments = 1 << pset->draw_step;
@@ -2115,14 +1917,14 @@ static bool psys_thread_context_init_path(
if (totchild && part->childtype == PART_CHILD_FACES) {
totparent = (int)(totchild * part->parents * 0.3f);
- if ((psys->renderdata || use_render_params) && part->child_nbr && part->ren_child_nbr)
+ if (use_render_params && part->child_nbr && part->ren_child_nbr)
totparent *= (float)part->child_nbr / (float)part->ren_child_nbr;
/* part->parents could still be 0 so we can't test with totparent */
between = 1;
}
- if (psys->renderdata || use_render_params)
+ if (use_render_params)
segments = 1 << part->ren_step;
else {
totchild = (int)((float)totchild * (float)part->disp / 100.0f);
@@ -2154,6 +1956,7 @@ static bool psys_thread_context_init_path(
ctx->vg_rough1 = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_ROUGH1);
ctx->vg_rough2 = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_ROUGH2);
ctx->vg_roughe = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_ROUGHE);
+ ctx->vg_twist = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_TWIST);
if (psys->part->flag & PART_CHILD_EFFECT)
ctx->vg_effector = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_EFFECTOR);
@@ -2172,6 +1975,13 @@ static bool psys_thread_context_init_path(
else {
ctx->roughcurve = NULL;
}
+ if ((part->child_flag & PART_CHILD_USE_TWIST_CURVE) && part->twistcurve) {
+ ctx->twistcurve = curvemapping_copy(part->twistcurve);
+ curvemapping_changed_all(ctx->twistcurve);
+ }
+ else {
+ ctx->twistcurve = NULL;
+ }
return true;
}
@@ -2192,7 +2002,7 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp
ParticleSystem *psys = ctx->sim.psys;
ParticleSettings *part = psys->part;
ParticleCacheKey **cache = psys->childcache;
- ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.eval_ctx->view_layer, psys) && psys->edit ? psys->edit->pathcache : psys->pathcache;
+ ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.eval_ctx->depsgraph, psys) && psys->edit ? psys->edit->pathcache : psys->pathcache;
ParticleCacheKey *child, *key[4];
ParticleTexture ptex;
float *cpa_fuv = 0, *par_rot = 0, rot[4];
@@ -2316,7 +2126,19 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp
/* get the original coordinates (orco) for texture usage */
cpa_from = part->from;
- cpa_num = pa->num;
+
+ /*
+ * NOTE: Should in theory be the same as:
+ cpa_num = psys_particle_dm_face_lookup(
+ ctx->sim.psmd->dm_final,
+ ctx->sim.psmd->dm_deformed,
+ pa->num, pa->fuv,
+ NULL);
+ */
+ cpa_num = (ELEM(pa->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND))
+ ? pa->num
+ : pa->num_dmcache;
+
/* XXX hack to avoid messed up particle num and subsequent crash (#40733) */
if (cpa_num > ctx->sim.psmd->dm_final->getNumTessFaces(ctx->sim.psmd->dm_final))
cpa_num = 0;
@@ -2569,7 +2391,9 @@ static void cache_key_incremental_rotation(ParticleCacheKey *key0, ParticleCache
void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_render_params)
{
PARTICLE_PSMD;
+#if 0
ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
+#endif
ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
ParticleCacheKey *ca, **cache;
@@ -2590,7 +2414,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
float prev_tangent[3] = {0.0f, 0.0f, 0.0f}, hairmat[4][4];
float rotmat[3][3];
int k;
- int segments = (int)pow(2.0, (double)((psys->renderdata || use_render_params) ? part->ren_step : part->draw_step));
+ int segments = (int)pow(2.0, (double)((use_render_params) ? part->ren_step : part->draw_step));
int totpart = psys->totpart;
float length, vec[3];
float *vg_effector = NULL;
@@ -2601,9 +2425,11 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
if ((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache) == 0)
return;
- if (psys_in_edit_mode(sim->eval_ctx->view_layer, psys))
- if (psys->renderdata == 0 && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
+#if 0 /* TODO(mai): something is very wrong with these conditionals, they dont make sense and the cache isnt updating */
+ if (psys_in_edit_mode(sim->eval_ctx->depsgraph, psys))
+ if ((psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
return;
+#endif
keyed = psys->flag & PSYS_KEYED;
baked = psys->pointcache->mem_cache.first && psys->part->type != PART_HAIR;
@@ -3164,7 +2990,7 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n
psys->part = BKE_particlesettings_add(NULL, DATA_("ParticleSettings"));
- if (BLI_listbase_count_ex(&ob->particlesystem, 2) > 1)
+ if (BLI_listbase_count_at_most(&ob->particlesystem, 2) > 1)
BLI_snprintf(psys->name, sizeof(psys->name), DATA_("ParticleSystem %i"), BLI_listbase_count(&ob->particlesystem));
else
BLI_strncpy(psys->name, DATA_("ParticleSystem"), sizeof(psys->name));
@@ -3307,11 +3133,6 @@ static void default_particle_settings(ParticleSettings *part)
part->color_vec_max = 1.f;
part->draw_col = PART_DRAW_COL_MAT;
- part->simplify_refsize = 1920;
- part->simplify_rate = 1.0f;
- part->simplify_transition = 0.1f;
- part->simplify_viewport = 0.8;
-
if (!part->effector_weights)
part->effector_weights = BKE_add_effector_weights(NULL);
@@ -3359,6 +3180,18 @@ void BKE_particlesettings_rough_curve_init(ParticleSettings *part)
part->roughcurve = cumap;
}
+void BKE_particlesettings_twist_curve_init(ParticleSettings *part)
+{
+ CurveMapping *cumap = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+
+ cumap->cm[0].curve[0].x = 0.0f;
+ cumap->cm[0].curve[0].y = 1.0f;
+ cumap->cm[0].curve[1].x = 1.0f;
+ cumap->cm[0].curve[1].y = 1.0f;
+
+ part->twistcurve = cumap;
+}
+
/**
* Only copy internal data of ParticleSettings ID from source to already allocated/initialized destination.
* You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
@@ -3381,6 +3214,9 @@ void BKE_particlesettings_copy_data(
if (part_src->roughcurve) {
part_dst->roughcurve = curvemapping_copy(part_src->roughcurve);
}
+ if (part_src->twistcurve) {
+ part_dst->twistcurve = curvemapping_copy(part_src->twistcurve);
+ }
part_dst->boids = boid_copy_settings(part_src->boids);
@@ -3500,6 +3336,7 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti
ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp =
ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink_freq = ptex->kink_amp =
ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f;
+ ptex->twist = 1.0f;
ptex->length = 1.0f - part->randlength * psys_frand(psys, child_index + 26);
ptex->length *= part->clength_thres < psys_frand(psys, child_index + 27) ? part->clength : 1.0f;
@@ -3552,6 +3389,7 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti
SET_PARTICLE_TEXTURE(PAMAP_KINK_AMP, ptex->kink_amp, mtex->kinkampfac);
SET_PARTICLE_TEXTURE(PAMAP_KINK_FREQ, ptex->kink_freq, mtex->kinkfac);
SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac);
+ SET_PARTICLE_TEXTURE(PAMAP_TWIST, ptex->twist, mtex->twistfac);
}
}
@@ -3577,6 +3415,7 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex
ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp =
ptex->gravity = ptex->field = ptex->length = ptex->clump = ptex->kink_freq = ptex->kink_amp =
ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f;
+ ptex->twist = 1.0f;
ptex->time = (float)(pa - sim->psys->particles) / (float)sim->psys->totpart;
@@ -3651,6 +3490,7 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex
SET_PARTICLE_TEXTURE(PAMAP_GRAVITY, ptex->gravity, mtex->gravityfac);
SET_PARTICLE_TEXTURE(PAMAP_DAMP, ptex->damp, mtex->dampfac);
SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac);
+ SET_PARTICLE_TEXTURE(PAMAP_TWIST, ptex->twist, mtex->twistfac);
}
}
@@ -3742,6 +3582,8 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread
ptex->roughe *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_roughe);
if (ctx->vg_effector)
ptex->effector *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_effector);
+ if (ctx->vg_twist)
+ ptex->twist *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_twist);
}
/* get's hair (or keyed) particles state at the "path time" specified in state->time */
void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *state, const bool vel)
@@ -3794,7 +3636,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
/* pind.dm disabled in editmode means we don't get effectors taken into
* account when subdividing for instance */
- pind.dm = psys_in_edit_mode(sim->eval_ctx->view_layer, psys) ? NULL : psys->hair_out_dm;
+ pind.dm = psys_in_edit_mode(sim->eval_ctx->depsgraph, psys) ? NULL : psys->hair_out_dm;
init_particle_interpolation(sim->ob, psys, pa, &pind);
do_particle_interpolation(psys, p, pa, t, &pind, state);
@@ -3947,7 +3789,18 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
copy_particle_key(&tstate, state, 1);
/* apply different deformations to the child path */
- do_child_modifiers(NULL, sim, &ptex, par->co, par->vel, par->rot, par_orco, cpa, orco, hairmat, state, t);
+ ParticleChildModifierContext modifier_ctx = {NULL};
+ modifier_ctx.thread_ctx = NULL;
+ modifier_ctx.sim = sim;
+ modifier_ctx.ptex = &ptex;
+ modifier_ctx.cpa = cpa;
+ modifier_ctx.orco = orco;
+ modifier_ctx.par_co = par->co;
+ modifier_ctx.par_vel = par->vel;
+ modifier_ctx.par_rot = par->rot;
+ modifier_ctx.par_orco = par_orco;
+ modifier_ctx.parent_keys = psys->childcache ? psys->childcache[p - totpart] : NULL;
+ do_child_modifiers(&modifier_ctx, hairmat, state, t);
/* try to estimate correct velocity */
if (vel) {
@@ -4050,7 +3903,19 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
CLAMP(t, 0.0f, 1.0f);
unit_m4(mat);
- do_child_modifiers(NULL, sim, NULL, key1->co, key1->vel, key1->rot, par_orco, cpa, cpa->fuv, mat, state, t);
+ ParticleChildModifierContext modifier_ctx = {NULL};
+ modifier_ctx.thread_ctx = NULL;
+ modifier_ctx.sim = sim;
+ modifier_ctx.ptex = NULL;
+ modifier_ctx.cpa = cpa;
+ modifier_ctx.orco = cpa->fuv;
+ modifier_ctx.par_co = key1->co;
+ modifier_ctx.par_vel = key1->vel;
+ modifier_ctx.par_rot = key1->rot;
+ modifier_ctx.par_orco = par_orco;
+ modifier_ctx.parent_keys = psys->childcache ? psys->childcache[p - totpart] : NULL;
+
+ do_child_modifiers(&modifier_ctx, mat, state, t);
if (psys->lattice_deform_data)
calc_latt_deform(psys->lattice_deform_data, state->co, psys->lattice_strength);
diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c
index d2ad05c20b7..c2640e9b9e2 100644
--- a/source/blender/blenkernel/intern/particle_child.c
+++ b/source/blender/blenkernel/intern/particle_child.c
@@ -37,15 +37,9 @@
#include "BKE_colortools.h"
#include "BKE_particle.h"
-struct Material;
+#include "particle_private.h"
-void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape, float amplitude, float flat,
- short type, short axis, float obmat[4][4], int smooth_start);
-float do_clump(ParticleKey *state, const float par_co[3], float time, const float orco_offset[3], float clumpfac, float clumppow, float pa_clump,
- bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve);
-void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim,
- ParticleTexture *ptex, const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3],
- ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t);
+struct Material;
static void get_strand_normal(Material *ma, const float surfnor[3], float surfdist, float nor[3])
{
@@ -67,7 +61,7 @@ static void get_strand_normal(Material *ma, const float surfnor[3], float surfdi
else {
copy_v3_v3(vnor, nor);
}
-
+
if (ma->strand_surfnor > 0.0f) {
if (ma->strand_surfnor > surfdist) {
blend = (ma->strand_surfnor - surfdist) / ma->strand_surfnor;
@@ -85,7 +79,7 @@ typedef struct ParticlePathIterator {
ParticleCacheKey *key;
int index;
float time;
-
+
ParticleCacheKey *parent_key;
float parent_rotation[4];
} ParticlePathIterator;
@@ -94,11 +88,11 @@ static void psys_path_iter_get(ParticlePathIterator *iter, ParticleCacheKey *key
ParticleCacheKey *parent, int index)
{
BLI_assert(index >= 0 && index < totkeys);
-
+
iter->key = keys + index;
iter->index = index;
iter->time = (float)index / (float)(totkeys - 1);
-
+
if (parent) {
iter->parent_key = parent + index;
if (index > 0)
@@ -114,7 +108,7 @@ static void psys_path_iter_get(ParticlePathIterator *iter, ParticleCacheKey *key
typedef struct ParticlePathModifier {
struct ParticlePathModifier *next, *prev;
-
+
void (*apply)(ParticleCacheKey *keys, int totkeys, ParticleCacheKey *parent_keys);
} ParticlePathModifier;
@@ -133,7 +127,7 @@ static void do_kink_spiral_deform(ParticleKey *state, const float dir[3], const
{
/* Creates a logarithmic spiral:
* r(theta) = a * exp(b * theta)
- *
+ *
* The "density" parameter b is defined by the shape parameter
* and goes up to the Golden Spiral for 1.0
* https://en.wikipedia.org/wiki/Golden_spiral
@@ -142,33 +136,33 @@ static void do_kink_spiral_deform(ParticleKey *state, const float dir[3], const
/* angle of the spiral against the curve (rotated opposite to make a smooth transition) */
const float start_angle = ((b != 0.0f) ? atanf(1.0f / b) :
(float)-M_PI_2) + (b > 0.0f ? -(float)M_PI_2 : (float)M_PI_2);
-
+
float spiral_axis[3], rot[3][3];
float vec[3];
-
+
float theta = freq * time * 2.0f * (float)M_PI;
float radius = amplitude * expf(b * theta);
-
+
/* a bit more intuitive than using negative frequency for this */
if (amplitude < 0.0f)
theta = -theta;
-
+
cross_v3_v3v3(spiral_axis, dir, kink);
normalize_v3(spiral_axis);
-
+
mul_v3_v3fl(vec, kink, -radius);
-
+
axis_angle_normalized_to_mat3(rot, spiral_axis, theta);
mul_m3_v3(rot, vec);
-
+
madd_v3_v3fl(vec, kink, amplitude);
-
+
axis_angle_normalized_to_mat3(rot, spiral_axis, -start_angle);
mul_m3_v3(rot, vec);
-
+
add_v3_v3v3(result, spiral_start, vec);
}
-
+
copy_v3_v3(state->co, result);
}
@@ -180,7 +174,7 @@ static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, co
const int seed = ctx->sim.psys->child_seed + (int)(cpa - ctx->sim.psys->child);
const int totkeys = ctx->segments + 1;
const int extrakeys = ctx->extra_segments;
-
+
float kink_amp_random = part->kink_amp_random;
float kink_amp = part->kink_amp * (1.0f - kink_amp_random * psys_frand(ctx->sim.psys, 93541 + seed));
float kink_freq = part->kink_freq;
@@ -189,11 +183,11 @@ static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, co
float rough1 = part->rough1;
float rough2 = part->rough2;
float rough_end = part->rough_end;
-
+
ParticlePathIterator iter;
ParticleCacheKey *key;
int k;
-
+
float dir[3];
float spiral_start[3] = {0.0f, 0.0f, 0.0f};
float spiral_start_time = 0.0f;
@@ -204,7 +198,7 @@ static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, co
float cut_time;
int start_index = 0, end_index = 0;
float kink_base[3];
-
+
if (ptex) {
kink_amp *= ptex->kink_amp;
kink_freq *= ptex->kink_freq;
@@ -212,44 +206,53 @@ static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, co
rough2 *= ptex->rough2;
rough_end *= ptex->roughe;
}
-
+
cut_time = (totkeys - 1) * ptex->length;
zero_v3(spiral_start);
-
+
for (k = 0, key = keys; k < totkeys-1; k++, key++) {
if ((float)(k + 1) >= cut_time) {
float fac = cut_time - (float)k;
ParticleCacheKey *par = parent_keys + k;
-
+
start_index = k + 1;
end_index = start_index + extrakeys;
-
+
spiral_start_time = ((float)k + fac) / (float)(totkeys - 1);
interp_v3_v3v3(spiral_start, key->co, (key+1)->co, fac);
-
+
interp_v3_v3v3(spiral_par_co, par->co, (par+1)->co, fac);
interp_v3_v3v3(spiral_par_vel, par->vel, (par+1)->vel, fac);
interp_qt_qtqt(spiral_par_rot, par->rot, (par+1)->rot, fac);
-
+
break;
}
}
-
+
zero_v3(dir);
-
+
zero_v3(kink_base);
kink_base[part->kink_axis] = 1.0f;
mul_mat3_m4_v3(ctx->sim.ob->obmat, kink_base);
-
+
+ /* Fill in invariant part of modifier context. */
+ ParticleChildModifierContext modifier_ctx = {NULL};
+ modifier_ctx.thread_ctx = ctx;
+ modifier_ctx.sim = &ctx->sim;
+ modifier_ctx.ptex = ptex;
+ modifier_ctx.cpa = cpa;
+ modifier_ctx.orco = orco;
+ modifier_ctx.parent_keys = parent_keys;
+
for (k = 0, key = keys; k < end_index; k++, key++) {
float par_time;
float *par_co, *par_vel, *par_rot;
-
+
psys_path_iter_get(&iter, keys, end_index, NULL, k);
if (k < start_index) {
sub_v3_v3v3(dir, (key+1)->co, key->co);
normalize_v3(dir);
-
+
par_time = (float)k / (float)(totkeys - 1);
par_co = parent_keys[k].co;
par_vel = parent_keys[k].vel;
@@ -258,36 +261,42 @@ static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, co
else {
float spiral_time = (float)(k - start_index) / (float)(extrakeys-1);
float kink[3], tmp[3];
-
+
/* use same time value for every point on the spiral */
par_time = spiral_start_time;
par_co = spiral_par_co;
par_vel = spiral_par_vel;
par_rot = spiral_par_rot;
-
+
project_v3_v3v3(tmp, kink_base, dir);
sub_v3_v3v3(kink, kink_base, tmp);
normalize_v3(kink);
-
+
if (kink_axis_random > 0.0f) {
float a = kink_axis_random * (psys_frand(ctx->sim.psys, 7112 + seed) * 2.0f - 1.0f) * (float)M_PI;
float rot[3][3];
-
+
axis_angle_normalized_to_mat3(rot, dir, a);
mul_m3_v3(rot, kink);
}
-
+
do_kink_spiral_deform((ParticleKey *)key, dir, kink, spiral_time, kink_freq, kink_shape, kink_amp, spiral_start);
}
-
- /* apply different deformations to the child path */
- do_child_modifiers(ctx, &ctx->sim, ptex, par_co, par_vel, par_rot, parent_orco, cpa, orco, hairmat, (ParticleKey *)key, par_time);
+
+ /* Fill in variant part of modifier context. */
+ modifier_ctx.par_co = par_co;
+ modifier_ctx.par_vel = par_vel;
+ modifier_ctx.par_rot = par_rot;
+ modifier_ctx.par_orco = parent_orco;
+
+ /* Apply different deformations to the child path/ */
+ do_child_modifiers(&modifier_ctx, hairmat, (ParticleKey *)key, par_time);
}
-
+
totlen = 0.0f;
for (k = 0, key = keys; k < end_index-1; k++, key++)
totlen += len_v3v3((key+1)->co, key->co);
-
+
*r_totkeys = end_index;
*r_max_length = totlen;
}
@@ -318,12 +327,12 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *mod
struct Material *ma = ctx->ma;
const bool draw_col_ma = (part->draw_col == PART_DRAW_COL_MAT);
const bool use_length_check = !ELEM(part->kink, PART_KINK_SPIRAL);
-
+
ParticlePathModifier *mod;
ParticleCacheKey *key;
int totkeys, k;
float max_length;
-
+
#if 0 /* TODO for the future: use true particle modifiers that work on the whole curve */
for (mod = modifiers->first; mod; mod = mod->next) {
mod->apply(keys, totkeys, parent_keys);
@@ -331,25 +340,38 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *mod
#else
(void)modifiers;
(void)mod;
-
+
if (part->kink == PART_KINK_SPIRAL) {
do_kink_spiral(ctx, ptex, parent_orco, cpa, orco, hairmat, keys, parent_keys, &totkeys, &max_length);
keys->segments = totkeys - 1;
}
else {
- ParticlePathIterator iter;
-
+ /* Fill in invariant part of modifier context. */
+ ParticleChildModifierContext modifier_ctx = {NULL};
+ modifier_ctx.thread_ctx = ctx;
+ modifier_ctx.sim = &ctx->sim;
+ modifier_ctx.ptex = ptex;
+ modifier_ctx.cpa = cpa;
+ modifier_ctx.orco = orco;
+ modifier_ctx.parent_keys = parent_keys;
+
totkeys = ctx->segments + 1;
max_length = ptex->length;
-
+
for (k = 0, key = keys; k < totkeys; k++, key++) {
- ParticleKey *par;
-
+ ParticlePathIterator iter;
psys_path_iter_get(&iter, keys, totkeys, parent_keys, k);
- par = (ParticleKey *)iter.parent_key;
-
- /* apply different deformations to the child path */
- do_child_modifiers(ctx, &ctx->sim, ptex, par->co, par->vel, iter.parent_rotation, parent_orco, cpa, orco, hairmat, (ParticleKey *)key, iter.time);
+
+ ParticleKey *par = (ParticleKey *)iter.parent_key;
+
+ /* Fill in variant part of modifier context. */
+ modifier_ctx.par_co = par->co;
+ modifier_ctx.par_vel = par->vel;
+ modifier_ctx.par_rot = iter.parent_rotation;
+ modifier_ctx.par_orco = parent_orco;
+
+ /* Apply different deformations to the child path. */
+ do_child_modifiers(&modifier_ctx, hairmat, (ParticleKey *)key, iter.time);
}
}
@@ -367,12 +389,12 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *mod
if (k >= 2) {
sub_v3_v3v3((key-1)->vel, key->co, (key-2)->co);
mul_v3_fl((key-1)->vel, 0.5);
-
+
if (ma && draw_col_ma)
get_strand_normal(ma, ornor, cur_length, (key-1)->vel);
}
-
- if (use_length_check && k > 1) {
+
+ if (use_length_check && k > 0) {
float dvec[3];
/* check if path needs to be cut before actual end of data points */
if (!check_path_length(k, keys, key, max_length, step_length, &cur_length, dvec)) {
@@ -388,7 +410,7 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *mod
/* last key */
sub_v3_v3v3(key->vel, key->co, (key-1)->co);
}
-
+
if (ma && draw_col_ma) {
copy_v3_v3(key->col, &ma->r);
get_strand_normal(ma, ornor, cur_length, key->vel);
@@ -419,7 +441,7 @@ void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3],
}
t = time * freq * (float)M_PI;
-
+
if (smooth_start) {
dt = fabsf(t);
/* smooth the beginning of kink */
@@ -434,7 +456,7 @@ void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3],
if (obmat)
mul_mat3_m4_v3(obmat, kink);
-
+
mul_qt_v3(par_rot, kink);
/* make sure kink is normal to strand */
@@ -450,12 +472,12 @@ void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3],
case PART_KINK_CURL:
{
float curl_offset[3];
-
+
/* rotate kink vector around strand tangent */
mul_v3_v3fl(curl_offset, kink, amplitude);
axis_angle_to_quat(q1, par_vel, t);
mul_qt_v3(q1, curl_offset);
-
+
interp_v3_v3v3(par_vec, state->co, par_co, flat);
add_v3_v3v3(result, par_vec, curl_offset);
break;
@@ -494,7 +516,7 @@ void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3],
float z_vec[3] = {0.f, 0.f, 1.f};
float vec_one[3], state_co[3];
float inp_y, inp_z, length;
-
+
if (par_rot) {
mul_qt_v3(par_rot, y_vec);
mul_qt_v3(par_rot, z_vec);
@@ -563,10 +585,10 @@ static float do_clump_level(float result[3], const float co[3], const float par_
float clumpfac, float clumppow, float pa_clump, CurveMapping *clumpcurve)
{
float clump = 0.0f;
-
+
if (clumpcurve) {
- clump = pa_clump * (1.0f - CLAMPIS(curvemapping_evaluateF(clumpcurve, 0, time), 0.0f, 1.0f));
-
+ clump = pa_clump * (1.0f - clamp_f(curvemapping_evaluateF(clumpcurve, 0, time), 0.0f, 1.0f));
+
interp_v3_v3v3(result, co, par_co, clump);
}
else if (clumpfac != 0.0f) {
@@ -584,7 +606,7 @@ static float do_clump_level(float result[3], const float co[3], const float par_
interp_v3_v3v3(result, co, par_co, clump);
}
-
+
return clump;
}
@@ -592,21 +614,21 @@ float do_clump(ParticleKey *state, const float par_co[3], float time, const floa
bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve)
{
float clump;
-
+
if (use_clump_noise && clump_noise_size != 0.0f) {
float center[3], noisevec[3];
float da[4], pa[12];
-
+
mul_v3_v3fl(noisevec, orco_offset, 1.0f / clump_noise_size);
voronoi(noisevec[0], noisevec[1], noisevec[2], da, pa, 1.0f, 0);
mul_v3_fl(&pa[0], clump_noise_size);
add_v3_v3v3(center, par_co, &pa[0]);
-
+
do_clump_level(state->co, state->co, center, time, clumpfac, clumppow, pa_clump, clumpcurve);
}
-
+
clump = do_clump_level(state->co, state->co, par_co, time, clumpfac, clumppow, pa_clump, clumpcurve);
-
+
return clump;
}
@@ -651,27 +673,117 @@ static void do_rough_curve(const float loc[3], float mat[4][4], float time, floa
{
float rough[3];
float rco[3];
-
+
if (!roughcurve)
return;
-
- fac *= CLAMPIS(curvemapping_evaluateF(roughcurve, 0, time), 0.0f, 1.0f);
-
+
+ fac *= clamp_f(curvemapping_evaluateF(roughcurve, 0, time), 0.0f, 1.0f);
+
copy_v3_v3(rco, loc);
mul_v3_fl(rco, time);
rough[0] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2, 0, 2);
rough[1] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2, 0, 2);
rough[2] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2, 0, 2);
-
+
madd_v3_v3fl(state->co, mat[0], fac * rough[0]);
madd_v3_v3fl(state->co, mat[1], fac * rough[1]);
madd_v3_v3fl(state->co, mat[2], fac * rough[2]);
}
-void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim, ParticleTexture *ptex,
- const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3],
- ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t)
+static int twist_num_segments(const ParticleChildModifierContext *modifier_ctx)
{
+ ParticleThreadContext *thread_ctx = modifier_ctx->thread_ctx;
+ return (thread_ctx != NULL) ? thread_ctx->segments
+ : modifier_ctx->sim->psys->part->draw_step;
+}
+
+static void twist_get_axis(const ParticleChildModifierContext *modifier_ctx,
+ const float time, float r_axis[3])
+{
+ const int num_segments = twist_num_segments(modifier_ctx);
+ const int index = clamp_i(time * num_segments, 0, num_segments);
+ if (index > 0) {
+ sub_v3_v3v3(r_axis,
+ modifier_ctx->parent_keys[index].co,
+ modifier_ctx->parent_keys[index - 1].co);
+ }
+ else {
+ sub_v3_v3v3(r_axis,
+ modifier_ctx->parent_keys[index + 1].co,
+ modifier_ctx->parent_keys[index].co);
+ }
+}
+
+static float curvemapping_integrate_clamped(CurveMapping *curve,
+ float start, float end, float step)
+{
+ float integral = 0.0f;
+ float x = start;
+ while (x < end) {
+ float y = curvemapping_evaluateF(curve, 0, x);
+ y = clamp_f(y, 0.0f, 1.0f);
+ /* TODO(sergey): Clamp last step to end. */
+ integral += y * step;
+ x += step;
+ }
+ return integral;
+}
+
+static void do_twist(const ParticleChildModifierContext *modifier_ctx,
+ ParticleKey *state, const float time)
+{
+ ParticleThreadContext *thread_ctx = modifier_ctx->thread_ctx;
+ ParticleSimulationData *sim = modifier_ctx->sim;
+ ParticleTexture *ptex = modifier_ctx->ptex;
+ ParticleSettings *part = sim->psys->part;
+ /* Early output checks. */
+ if (part->childtype != PART_CHILD_PARTICLES) {
+ /* Interpolated children behave weird with twist. */
+ return;
+ }
+ if (part->twist == 0.0f) {
+ /* No twist along the strand. */
+ return;
+ }
+ /* Dependent on whether it's threaded update or not, curve comes
+ * from different places.
+ */
+ CurveMapping *twist_curve = NULL;
+ if (part->child_flag & PART_CHILD_USE_TWIST_CURVE) {
+ twist_curve = (thread_ctx != NULL) ? thread_ctx->twistcurve
+ : part->twistcurve;
+ }
+ /* Axis of rotation. */
+ float axis[3];
+ twist_get_axis(modifier_ctx, time, axis);
+ /* Angle of rotation. */
+ float angle = part->twist;
+ if (ptex != NULL) {
+ angle *= (ptex->twist - 0.5f) * 2.0f;
+ }
+ if (twist_curve != NULL) {
+ const int num_segments = twist_num_segments(modifier_ctx);
+ angle *= curvemapping_integrate_clamped(twist_curve,
+ 0.0f, time,
+ 1.0f / num_segments);
+ }
+ else {
+ angle *= time;
+ }
+ /* Perform rotation around parent curve. */
+ float vec[3];
+ sub_v3_v3v3(vec, state->co, modifier_ctx->par_co);
+ rotate_v3_v3v3fl(state->co, vec, axis, angle * 2.0f * M_PI);
+ add_v3_v3(state->co, modifier_ctx->par_co);
+}
+
+void do_child_modifiers(const ParticleChildModifierContext *modifier_ctx,
+ float mat[4][4], ParticleKey *state, float t)
+{
+ ParticleThreadContext *ctx = modifier_ctx->thread_ctx;
+ ParticleSimulationData *sim = modifier_ctx->sim;
+ ParticleTexture *ptex = modifier_ctx->ptex;
+ ChildParticle *cpa = modifier_ctx->cpa;
ParticleSettings *part = sim->psys->part;
CurveMapping *clumpcurve = NULL, *roughcurve = NULL;
int i = cpa - sim->psys->child;
@@ -700,6 +812,8 @@ void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim,
rough_end *= ptex->roughe;
}
+ do_twist(modifier_ctx, state, t);
+
if (part->flag & PART_CHILD_EFFECT)
/* state is safe to cast, since only co and vel are used */
guided = do_guides(sim->eval_ctx, sim->psys->part, sim->psys->effectors, (ParticleKey *)state, cpa->parent, t);
@@ -707,33 +821,51 @@ void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim,
if (guided == 0) {
float orco_offset[3];
float clump;
-
- sub_v3_v3v3(orco_offset, orco, par_orco);
- clump = do_clump(state, par_co, t, orco_offset, part->clumpfac, part->clumppow, ptex ? ptex->clump : 1.f,
- part->child_flag & PART_CHILD_USE_CLUMP_NOISE, part->clump_noise_size, clumpcurve);
+
+ sub_v3_v3v3(orco_offset, modifier_ctx->orco, modifier_ctx->par_orco);
+ clump = do_clump(state,
+ modifier_ctx->par_co,
+ t,
+ orco_offset,
+ part->clumpfac,
+ part->clumppow,
+ ptex ? ptex->clump : 1.0f,
+ part->child_flag & PART_CHILD_USE_CLUMP_NOISE,
+ part->clump_noise_size,
+ clumpcurve);
if (kink_freq != 0.f) {
kink_amp *= (1.f - kink_amp_clump * clump);
-
- do_kink(state, par_co, par_vel, par_rot, t, kink_freq, part->kink_shape,
- kink_amp, part->kink_flat, part->kink, part->kink_axis,
- sim->ob->obmat, smooth_start);
+
+ do_kink(state,
+ modifier_ctx->par_co,
+ modifier_ctx->par_vel,
+ modifier_ctx->par_rot,
+ t,
+ kink_freq,
+ part->kink_shape,
+ kink_amp,
+ part->kink_flat,
+ part->kink,
+ part->kink_axis,
+ sim->ob->obmat,
+ smooth_start);
}
}
if (roughcurve) {
- do_rough_curve(orco, mat, t, rough1, part->rough1_size, roughcurve, state);
+ do_rough_curve(modifier_ctx->orco, mat, t, rough1, part->rough1_size, roughcurve, state);
}
else {
if (rough1 > 0.f)
- do_rough(orco, mat, t, rough1, part->rough1_size, 0.0, state);
-
+ do_rough(modifier_ctx->orco, mat, t, rough1, part->rough1_size, 0.0, state);
+
if (rough2 > 0.f) {
float vec[3];
psys_frand_vec(sim->psys, i + 27, vec);
do_rough(vec, mat, t, rough2, part->rough2_size, part->rough2_thres, state);
}
-
+
if (rough_end > 0.f) {
float vec[3];
psys_frand_vec(sim->psys, i + 27, vec);
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index ff8a638089f..c261b0dc22c 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -36,7 +36,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
-#include "BLI_jitter.h"
+#include "BLI_jitter_2d.h"
#include "BLI_kdtree.h"
#include "BLI_math.h"
#include "BLI_math_geom.h"
@@ -57,7 +57,7 @@
#include "BKE_object.h"
#include "BKE_particle.h"
-static int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot);
+#include "DEG_depsgraph_query.h"
static void alloc_child_particles(ParticleSystem *psys, int tot)
{
@@ -80,12 +80,12 @@ static void alloc_child_particles(ParticleSystem *psys, int tot)
}
}
-static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, DerivedMesh *deformdm, ParticleSystem *psys)
+static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, DerivedMesh *deformdm, ParticleSystem *psys, const bool use_render_params)
{
ChildParticle *cpa = NULL;
int i, p;
- int child_nbr= psys_get_child_number(scene, psys);
- int totpart= psys_get_tot_child(scene, psys);
+ int child_nbr= psys_get_child_number(scene, psys, use_render_params);
+ int totpart= psys_get_tot_child(scene, psys, use_render_params);
alloc_child_particles(psys, totpart);
@@ -738,16 +738,10 @@ static void exec_distribute_child(TaskPool * __restrict UNUSED(pool), void *task
/* RNG skipping at the beginning */
cpa = psys->child;
for (p = 0; p < task->begin; ++p, ++cpa) {
- if (task->ctx->skip) /* simplification skip */
- BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->ctx->skip[p]);
-
BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP);
}
for (; p < task->end; ++p, ++cpa) {
- if (task->ctx->skip) /* simplification skip */
- BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->ctx->skip[p]);
-
distribute_children_exec(task, cpa, p);
}
}
@@ -774,11 +768,15 @@ static int distribute_compare_orig_index(const void *p1, const void *p2, void *u
return 1;
}
-static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from)
+static void distribute_invalid(ParticleSimulationData *sim, int from)
{
+ Scene *scene = sim->scene;
+ ParticleSystem *psys = sim->psys;
+ const bool use_render_params = (DEG_get_mode(sim->eval_ctx->depsgraph) == DAG_EVAL_RENDER);
+
if (from == PART_FROM_CHILD) {
ChildParticle *cpa;
- int p, totchild = psys_get_tot_child(scene, psys);
+ int p, totchild = psys_get_tot_child(scene, psys, use_render_params);
if (psys->child && totchild) {
for (p=0,cpa=psys->child; p<totchild; p++,cpa++) {
@@ -800,7 +798,7 @@ static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from)
}
}
-/* Creates a distribution of coordinates on a DerivedMesh */
+/* Creates a distribution of coordinates on a DerivedMesh */
/* This is to denote functionality that does not yet work with mesh - only derived mesh */
static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, ParticleSimulationData *sim, int from)
{
@@ -841,13 +839,15 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
*/
psys_thread_context_init(ctx, sim);
+
+ const bool use_render_params = (DEG_get_mode(sim->eval_ctx->depsgraph) == DAG_EVAL_RENDER);
/* First handle special cases */
if (from == PART_FROM_CHILD) {
/* Simple children */
if (part->childtype != PART_CHILD_FACES) {
BLI_srandom(31415926 + psys->seed + psys->child_seed);
- distribute_simple_children(scene, ob, finaldm, sim->psmd->dm_deformed, psys);
+ distribute_simple_children(scene, ob, finaldm, sim->psmd->dm_deformed, psys, use_render_params);
return 0;
}
}
@@ -895,7 +895,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
BLI_kdtree_balance(tree);
- totpart = psys_get_tot_child(scene, psys);
+ totpart = psys_get_tot_child(scene, psys, use_render_params);
cfrom = from = PART_FROM_FACE;
}
else {
@@ -938,7 +938,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumTessFaces(dm);
if (totelem == 0) {
- distribute_invalid(scene, psys, children ? PART_FROM_CHILD : 0);
+ distribute_invalid(sim, children ? PART_FROM_CHILD : 0);
if (G.debug & G_DEBUG)
fprintf(stderr,"Particle distribution error: Nothing to emit from!\n");
@@ -950,9 +950,9 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
return 0;
}
- element_weight = MEM_callocN(sizeof(float)*totelem, "particle_distribution_weights");
- particle_element= MEM_callocN(sizeof(int)*totpart, "particle_distribution_indexes");
- jitter_offset = MEM_callocN(sizeof(float)*totelem, "particle_distribution_jitoff");
+ element_weight = MEM_callocN(sizeof(float) * totelem, "particle_distribution_weights");
+ particle_element = MEM_callocN(sizeof(int) * totpart, "particle_distribution_indexes");
+ jitter_offset = MEM_callocN(sizeof(float) * totelem, "particle_distribution_jitoff");
/* Calculate weights from face areas */
if ((part->flag&PART_EDISTR || children) && from != PART_FROM_VERT) {
@@ -1082,7 +1082,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
totmapped = i_mapped;
/* Finally assign elements to particles */
- if ((part->flag & PART_TRAND) || (part->simplify_flag & PART_SIMPLIFY_ENABLE)) {
+ if (part->flag & PART_TRAND) {
for (p = 0; p < totpart; p++) {
/* In theory element_sum[totmapped - 1] should be 1.0,
* but due to float errors this is not necessarily always true, so scale pos accordingly. */
@@ -1101,7 +1101,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
/* This is to address tricky issues with vertex-emitting when user tries (and expects) exact 1-1 vert/part
* distribution (see T47983 and its two example files). It allows us to consider pos as
* 'midpoint between v and v+1' (or 'p and p+1', depending whether we have more vertices than particles or not),
- * and avoid stumbling over float imprecisions in element_sum.
+ * and avoid stumbling over float impression in element_sum.
* Note: moved face and volume distribution to this as well (instead of starting at zero),
* for the same reasons, see T52682. */
pos = (totpart < totmapped) ? 0.5 / (double)totmapped : step * 0.5; /* We choose the smaller step. */
@@ -1176,7 +1176,6 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
ctx->tpars= tpars;
if (children) {
- totpart= psys_render_simplify_distribution(ctx, totpart);
alloc_child_particles(psys, totpart);
}
@@ -1235,7 +1234,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
/* ready for future use, to emit particles without geometry */
static void distribute_particles_on_shape(ParticleSimulationData *sim, int UNUSED(from))
{
- distribute_invalid(sim->scene, sim->psys, 0);
+ distribute_invalid(sim, 0);
fprintf(stderr,"Shape emission not yet possible!\n");
}
@@ -1255,250 +1254,8 @@ void distribute_particles(ParticleSimulationData *sim, int from)
distribute_particles_on_shape(sim, from);
if (distr_error) {
- distribute_invalid(sim->scene, sim->psys, from);
+ distribute_invalid(sim, from);
fprintf(stderr,"Particle distribution error!\n");
}
}
-
-/* ======== Simplify ======== */
-
-static float psys_render_viewport_falloff(double rate, float dist, float width)
-{
- return pow(rate, dist / width);
-}
-
-static float psys_render_projected_area(ParticleSystem *psys, const float center[3], float area, double vprate, float *viewport)
-{
- ParticleRenderData *data = psys->renderdata;
- float co[4], view[3], ortho1[3], ortho2[3], w, dx, dy, radius;
-
- /* transform to view space */
- copy_v3_v3(co, center);
- co[3] = 1.0f;
- mul_m4_v4(data->viewmat, co);
-
- /* compute two vectors orthogonal to view vector */
- normalize_v3_v3(view, co);
- ortho_basis_v3v3_v3(ortho1, ortho2, view);
-
- /* compute on screen minification */
- w = co[2] * data->winmat[2][3] + data->winmat[3][3];
- dx = data->winx * ortho2[0] * data->winmat[0][0];
- dy = data->winy * ortho2[1] * data->winmat[1][1];
- w = sqrtf(dx * dx + dy * dy) / w;
-
- /* w squared because we are working with area */
- area = area * w * w;
-
- /* viewport of the screen test */
-
- /* project point on screen */
- mul_m4_v4(data->winmat, co);
- if (co[3] != 0.0f) {
- co[0] = 0.5f * data->winx * (1.0f + co[0] / co[3]);
- co[1] = 0.5f * data->winy * (1.0f + co[1] / co[3]);
- }
-
- /* screen space radius */
- radius = sqrtf(area / (float)M_PI);
-
- /* make smaller using fallof once over screen edge */
- *viewport = 1.0f;
-
- if (co[0] + radius < 0.0f)
- *viewport *= psys_render_viewport_falloff(vprate, -(co[0] + radius), data->winx);
- else if (co[0] - radius > data->winx)
- *viewport *= psys_render_viewport_falloff(vprate, (co[0] - radius) - data->winx, data->winx);
-
- if (co[1] + radius < 0.0f)
- *viewport *= psys_render_viewport_falloff(vprate, -(co[1] + radius), data->winy);
- else if (co[1] - radius > data->winy)
- *viewport *= psys_render_viewport_falloff(vprate, (co[1] - radius) - data->winy, data->winy);
-
- return area;
-}
-
-/* BMESH_TODO, for orig face data, we need to use MPoly */
-static int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
-{
- DerivedMesh *dm = ctx->dm;
- Mesh *me = (Mesh *)(ctx->sim.ob->data);
- MFace *mf, *mface;
- MVert *mvert;
- ParticleRenderData *data;
- ParticleRenderElem *elems, *elem;
- ParticleSettings *part = ctx->sim.psys->part;
- float *facearea, (*facecenter)[3], size[3], fac, powrate, scaleclamp;
- float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport;
- double vprate;
- int *facetotvert;
- int a, b, totorigface, totface, newtot, skipped;
-
- /* double lookup */
- const int *index_mf_to_mpoly;
- const int *index_mp_to_orig;
-
- if (part->ren_as != PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND))
- return tot;
- if (!ctx->sim.psys->renderdata)
- return tot;
-
- data = ctx->sim.psys->renderdata;
- if (data->timeoffset)
- return 0;
- if (!(part->simplify_flag & PART_SIMPLIFY_ENABLE))
- return tot;
-
- mvert = dm->getVertArray(dm);
- mface = dm->getTessFaceArray(dm);
- totface = dm->getNumTessFaces(dm);
- totorigface = me->totpoly;
-
- if (totface == 0 || totorigface == 0)
- return tot;
-
- index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
- index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
-
- facearea = MEM_callocN(sizeof(float) * totorigface, "SimplifyFaceArea");
- facecenter = MEM_callocN(sizeof(float[3]) * totorigface, "SimplifyFaceCenter");
- facetotvert = MEM_callocN(sizeof(int) * totorigface, "SimplifyFaceArea");
- elems = MEM_callocN(sizeof(ParticleRenderElem) * totorigface, "SimplifyFaceElem");
-
- if (data->elems)
- MEM_freeN(data->elems);
-
- data->do_simplify = true;
- data->elems = elems;
- data->index_mf_to_mpoly = index_mf_to_mpoly;
- data->index_mp_to_orig = index_mp_to_orig;
-
- /* compute number of children per original face */
- for (a = 0; a < tot; a++) {
- b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a];
- if (b != ORIGINDEX_NONE) {
- elems[b].totchild++;
- }
- }
-
- /* compute areas and centers of original faces */
- for (mf = mface, a = 0; a < totface; a++, mf++) {
- b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
-
- if (b != ORIGINDEX_NONE) {
- copy_v3_v3(co1, mvert[mf->v1].co);
- copy_v3_v3(co2, mvert[mf->v2].co);
- copy_v3_v3(co3, mvert[mf->v3].co);
-
- add_v3_v3(facecenter[b], co1);
- add_v3_v3(facecenter[b], co2);
- add_v3_v3(facecenter[b], co3);
-
- if (mf->v4) {
- copy_v3_v3(co4, mvert[mf->v4].co);
- add_v3_v3(facecenter[b], co4);
- facearea[b] += area_quad_v3(co1, co2, co3, co4);
- facetotvert[b] += 4;
- }
- else {
- facearea[b] += area_tri_v3(co1, co2, co3);
- facetotvert[b] += 3;
- }
- }
- }
-
- for (a = 0; a < totorigface; a++)
- if (facetotvert[a] > 0)
- mul_v3_fl(facecenter[a], 1.0f / facetotvert[a]);
-
- /* for conversion from BU area / pixel area to reference screen size */
- BKE_mesh_texspace_get(me, 0, 0, size);
- fac = ((size[0] + size[1] + size[2]) / 3.0f) / part->simplify_refsize;
- fac = fac * fac;
-
- powrate = log(0.5f) / log(part->simplify_rate * 0.5f);
- if (part->simplify_flag & PART_SIMPLIFY_VIEWPORT)
- vprate = pow(1.0f - part->simplify_viewport, 5.0);
- else
- vprate = 1.0;
-
- /* set simplification parameters per original face */
- for (a = 0, elem = elems; a < totorigface; a++, elem++) {
- area = psys_render_projected_area(ctx->sim.psys, facecenter[a], facearea[a], vprate, &viewport);
- arearatio = fac * area / facearea[a];
-
- if ((arearatio < 1.0f || viewport < 1.0f) && elem->totchild) {
- /* lambda is percentage of elements to keep */
- lambda = (arearatio < 1.0f) ? powf(arearatio, powrate) : 1.0f;
- lambda *= viewport;
-
- lambda = MAX2(lambda, 1.0f / elem->totchild);
-
- /* compute transition region */
- t = part->simplify_transition;
- elem->t = (lambda - t < 0.0f) ? lambda : (lambda + t > 1.0f) ? 1.0f - lambda : t;
- elem->reduce = 1;
-
- /* scale at end and beginning of the transition region */
- elem->scalemax = (lambda + t < 1.0f) ? 1.0f / lambda : 1.0f / (1.0f - elem->t * elem->t / t);
- elem->scalemin = (lambda + t < 1.0f) ? 0.0f : elem->scalemax * (1.0f - elem->t / t);
-
- elem->scalemin = sqrtf(elem->scalemin);
- elem->scalemax = sqrtf(elem->scalemax);
-
- /* clamp scaling */
- scaleclamp = (float)min_ii(elem->totchild, 10);
- elem->scalemin = MIN2(scaleclamp, elem->scalemin);
- elem->scalemax = MIN2(scaleclamp, elem->scalemax);
-
- /* extend lambda to include transition */
- lambda = lambda + elem->t;
- if (lambda > 1.0f)
- lambda = 1.0f;
- }
- else {
- lambda = arearatio;
-
- elem->scalemax = 1.0f; //sqrt(lambda);
- elem->scalemin = 1.0f; //sqrt(lambda);
- elem->reduce = 0;
- }
-
- elem->lambda = lambda;
- elem->scalemin = sqrtf(elem->scalemin);
- elem->scalemax = sqrtf(elem->scalemax);
- elem->curchild = 0;
- }
-
- MEM_freeN(facearea);
- MEM_freeN(facecenter);
- MEM_freeN(facetotvert);
-
- /* move indices and set random number skipping */
- ctx->skip = MEM_callocN(sizeof(int) * tot, "SimplificationSkip");
-
- skipped = 0;
- for (a = 0, newtot = 0; a < tot; a++) {
- b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a];
-
- if (b != ORIGINDEX_NONE) {
- if (elems[b].curchild++ < ceil(elems[b].lambda * elems[b].totchild)) {
- ctx->index[newtot] = ctx->index[a];
- ctx->skip[newtot] = skipped;
- skipped = 0;
- newtot++;
- }
- else skipped++;
- }
- else skipped++;
- }
-
- for (a = 0, elem = elems; a < totorigface; a++, elem++)
- elem->curchild = 0;
-
- return newtot;
-}
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index ac10ad44bf1..ffe6617d561 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -48,7 +48,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
#include "DNA_curve_types.h"
#include "DNA_scene_types.h"
@@ -58,7 +58,7 @@
#include "BLI_utildefines.h"
#include "BLI_edgehash.h"
#include "BLI_rand.h"
-#include "BLI_jitter.h"
+#include "BLI_jitter_2d.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_kdtree.h"
@@ -76,7 +76,6 @@
#include "BKE_effect.h"
#include "BKE_library_query.h"
#include "BKE_particle.h"
-#include "BKE_global.h"
#include "BKE_collection.h"
#include "BKE_DerivedMesh.h"
@@ -91,6 +90,7 @@
#include "BKE_bvhutils.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "PIL_time.h"
@@ -98,7 +98,7 @@
/* fluid sim particle import */
#ifdef WITH_MOD_FLUID
-#include "DNA_object_fluidsim.h"
+#include "DNA_object_fluidsim_types.h"
#include "LBM_fluidsim.h"
#include <zlib.h>
#include <string.h>
@@ -122,11 +122,11 @@ static int particles_are_dynamic(ParticleSystem *psys)
return ELEM(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID);
}
-float psys_get_current_display_percentage(ParticleSystem *psys)
+float psys_get_current_display_percentage(ParticleSystem *psys, const bool use_render_params)
{
ParticleSettings *part=psys->part;
- if ((psys->renderdata && !particles_are_dynamic(psys)) || /* non-dynamic particles can be rendered fully */
+ if ((use_render_params && !particles_are_dynamic(psys)) || /* non-dynamic particles can be rendered fully */
(part->child_nbr && part->childtype) || /* display percentage applies to children */
(psys->pointcache->flag & PTCACHE_BAKING)) /* baking is always done with full amount */
{
@@ -286,24 +286,24 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart)
}
}
-int psys_get_child_number(Scene *scene, ParticleSystem *psys)
+int psys_get_child_number(Scene *scene, ParticleSystem *psys, const bool use_render_params)
{
int nbr;
if (!psys->part->childtype)
return 0;
- if (psys->renderdata)
+ if (use_render_params)
nbr= psys->part->ren_child_nbr;
else
nbr= psys->part->child_nbr;
- return get_render_child_particle_number(&scene->r, nbr, psys->renderdata != NULL);
+ return get_render_child_particle_number(&scene->r, nbr, use_render_params);
}
-int psys_get_tot_child(Scene *scene, ParticleSystem *psys)
+int psys_get_tot_child(Scene *scene, ParticleSystem *psys, const bool use_render_params)
{
- return psys->totpart*psys_get_child_number(scene, psys);
+ return psys->totpart*psys_get_child_number(scene, psys, use_render_params);
}
/************************************************/
@@ -499,6 +499,8 @@ void psys_thread_context_free(ParticleThreadContext *ctx)
MEM_freeN(ctx->vg_rough2);
if (ctx->vg_roughe)
MEM_freeN(ctx->vg_roughe);
+ if (ctx->vg_twist)
+ MEM_freeN(ctx->vg_twist);
if (ctx->sim.psys->lattice_deform_data) {
end_latt_deform(ctx->sim.psys->lattice_deform_data);
@@ -510,7 +512,6 @@ void psys_thread_context_free(ParticleThreadContext *ctx)
if (ctx->jitoff) MEM_freeN(ctx->jitoff);
if (ctx->weight) MEM_freeN(ctx->weight);
if (ctx->index) MEM_freeN(ctx->index);
- if (ctx->skip) MEM_freeN(ctx->skip);
if (ctx->seams) MEM_freeN(ctx->seams);
//if (ctx->vertpart) MEM_freeN(ctx->vertpart);
BLI_kdtree_free(ctx->tree);
@@ -521,6 +522,9 @@ void psys_thread_context_free(ParticleThreadContext *ctx)
if (ctx->roughcurve != NULL) {
curvemapping_free(ctx->roughcurve);
}
+ if (ctx->twistcurve != NULL) {
+ curvemapping_free(ctx->twistcurve);
+ }
}
static void initialize_particle_texture(ParticleSimulationData *sim, ParticleData *pa, int p)
@@ -2898,10 +2902,12 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
{
ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
+#if 0
ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
+#endif
int distr=0, alloc=0, skip=0;
- if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET)
+ if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys, use_render_params)) || psys->recalc&PSYS_RECALC_RESET)
alloc=1;
if (alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (sim->ob && sim->ob->mode & OB_MODE_WEIGHT_PAINT)))
@@ -2911,7 +2917,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
if (alloc)
realloc_particles(sim, sim->psys->totpart);
- if (psys_get_tot_child(sim->scene, psys)) {
+ if (psys_get_tot_child(sim->scene, psys, use_render_params)) {
/* don't generate children while computing the hair keys */
if (!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) {
distribute_particles(sim, PART_FROM_CHILD);
@@ -2928,22 +2934,25 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
skip = 1; /* only hair, keyed and baked stuff can have paths */
else if (part->ren_as != PART_DRAW_PATH && !(part->type==PART_HAIR && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)))
skip = 1; /* particle visualization must be set as path */
- else if (!psys->renderdata) {
+ else {
if (part->draw_as != PART_DRAW_REND)
skip = 1; /* draw visualization */
else if (psys->pointcache->flag & PTCACHE_BAKING)
skip = 1; /* no need to cache paths while baking dynamics */
- else if (psys_in_edit_mode(sim->eval_ctx->view_layer, psys)) {
+
+#if 0 /* TODO(mai): something is very wrong with these conditionals, they dont make sense and the cache isnt updating */
+ else if (psys_in_edit_mode(sim->eval_ctx->depsgraph, psys)) {
if ((pset->flag & PE_DRAW_PART)==0)
skip = 1;
else if (part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0)
skip = 1; /* in edit mode paths are needed for child particles and dynamic hair */
}
+#endif
}
/* particle instance modifier with "path" option need cached paths even if particle system doesn't */
- FOREACH_SCENE_OBJECT(sim->scene, ob)
+ FOREACH_SCENE_OBJECT_BEGIN(sim->scene, ob)
{
ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleInstance);
if (md) {
@@ -2954,7 +2963,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
}
}
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
if (!skip) {
psys_cache_paths(sim, cfra, use_render_params);
@@ -3214,7 +3223,7 @@ static void hair_step(ParticleSimulationData *sim, float cfra, const bool use_re
ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
PARTICLE_P;
- float disp = psys_get_current_display_percentage(psys);
+ float disp = psys_get_current_display_percentage(psys, use_render_params);
LOOP_PARTICLES {
pa->size = part->size;
@@ -3730,13 +3739,13 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
free_collider_cache(&sim->colliders);
BLI_rng_free(rng);
}
-static void update_children(ParticleSimulationData *sim)
+static void update_children(ParticleSimulationData *sim, const bool use_render_params)
{
if ((sim->psys->part->type == PART_HAIR) && (sim->psys->flag & PSYS_HAIR_DONE)==0)
/* don't generate children while growing hair - waste of time */
psys_free_children(sim->psys);
else if (sim->psys->part->childtype) {
- if (sim->psys->totchild != psys_get_tot_child(sim->scene, sim->psys))
+ if (sim->psys->totchild != psys_get_tot_child(sim->scene, sim->psys, use_render_params))
distribute_particles(sim, PART_FROM_CHILD);
else {
/* Children are up to date, nothing to do. */
@@ -3746,7 +3755,7 @@ static void update_children(ParticleSimulationData *sim)
psys_free_children(sim->psys);
}
/* updates cached particles' alive & other flags etc..*/
-static void cached_step(ParticleSimulationData *sim, float cfra)
+static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_render_params)
{
ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
@@ -3756,7 +3765,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra)
psys_update_effectors(sim);
- disp= psys_get_current_display_percentage(psys);
+ disp= psys_get_current_display_percentage(psys, use_render_params);
LOOP_PARTICLES {
psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra);
@@ -3978,8 +3987,8 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_
int cache_result = BKE_ptcache_read(pid, cache_cfra, true);
if (ELEM(cache_result, PTCACHE_READ_EXACT, PTCACHE_READ_INTERPOLATED)) {
- cached_step(sim, cfra);
- update_children(sim);
+ cached_step(sim, cfra, use_render_params);
+ update_children(sim, use_render_params);
psys_update_path_cache(sim, cfra, use_render_params);
BKE_ptcache_validate(cache, (int)cache_cfra);
@@ -3996,7 +4005,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_
}
else if (cache_result == PTCACHE_READ_OLD) {
psys->cfra = (float)cache->simframe;
- cached_step(sim, psys->cfra);
+ cached_step(sim, psys->cfra, use_render_params);
}
/* if on second frame, write cache for first frame */
@@ -4008,7 +4017,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_
/* 3. do dynamics */
/* set particles to be not calculated TODO: can't work with pointcache */
- disp= psys_get_current_display_percentage(psys);
+ disp= psys_get_current_display_percentage(psys, use_render_params);
LOOP_PARTICLES {
if (psys_frand(psys, p) > disp)
@@ -4064,7 +4073,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_
BKE_ptcache_write(pid, (int)cache_cfra);
}
- update_children(sim);
+ update_children(sim, use_render_params);
/* cleanup */
if (psys->lattice_deform_data) {
@@ -4307,7 +4316,7 @@ void particle_system_update(const struct EvaluationContext *eval_ctx, Scene *sce
case PART_PHYS_KEYED:
{
PARTICLE_P;
- float disp = psys_get_current_display_percentage(psys);
+ float disp = psys_get_current_display_percentage(psys, use_render_params);
bool free_unexisting = false;
/* Particles without dynamics haven't been reset yet because they don't use pointcache */
@@ -4369,8 +4378,7 @@ void particle_system_update(const struct EvaluationContext *eval_ctx, Scene *sce
psys->recalc = 0;
/* save matrix for duplicators, at rendertime the actual dupliobject's matrix is used so don't update! */
- if (psys->renderdata==0)
- invert_m4_m4(psys->imat, ob->obmat);
+ invert_m4_m4(psys->imat, ob->obmat);
BKE_particle_batch_cache_dirty(psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
}
@@ -4403,30 +4411,16 @@ void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func,
/* **** Depsgraph evaluation **** */
-void BKE_particle_system_settings_eval(const struct EvaluationContext *UNUSED(eval_ctx),
- ParticleSystem *psys)
-{
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s (%p)\n", __func__, psys->name, psys);
- }
- psys->recalc |= psys->part->recalc;
-}
-
-void BKE_particle_system_settings_recalc_clear(struct EvaluationContext *UNUSED(eval_ctx),
- ParticleSettings *particle_settings)
-{
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s (%p)\n", __func__, particle_settings->id.name, particle_settings);
- }
- particle_settings->recalc = 0;
-}
-
void BKE_particle_system_eval_init(const struct EvaluationContext *UNUSED(eval_ctx),
Scene *scene,
Object *ob)
{
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s (%p)\n", __func__, ob->id.name, ob);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
+ for (ParticleSystem *psys = ob->particlesystem.first;
+ psys != NULL;
+ psys = psys->next)
+ {
+ psys->recalc |= (psys->part->id.recalc & DEG_TAG_PSYS_ALL);
}
BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH);
}
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 63f2c7e5452..14e0cfa75b5 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1296,7 +1296,7 @@ void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *
pbvh_iter_end(&iter);
- const int tot = BLI_gset_size(face_set);
+ const int tot = BLI_gset_len(face_set);
if (tot == 0) {
*r_totface = 0;
*r_gridfaces = NULL;
@@ -1435,8 +1435,8 @@ void BKE_pbvh_node_num_verts(
if (r_uniquevert) *r_uniquevert = node->uniq_verts;
break;
case PBVH_BMESH:
- tot = BLI_gset_size(node->bm_unique_verts);
- if (r_totvert) *r_totvert = tot + BLI_gset_size(node->bm_other_verts);
+ tot = BLI_gset_len(node->bm_unique_verts);
+ if (r_totvert) *r_totvert = tot + BLI_gset_len(node->bm_other_verts);
if (r_uniquevert) *r_uniquevert = tot;
break;
}
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index e77edb21798..e32a5d0681e 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -255,7 +255,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
const int cd_face_node_offset = bvh->cd_face_node_offset;
PBVHNode *n = &bvh->nodes[node_index];
- if (BLI_gset_size(n->bm_faces) <= bvh->leaf_limit) {
+ if (BLI_gset_len(n->bm_faces) <= bvh->leaf_limit) {
/* Node limit not exceeded */
pbvh_bmesh_node_finalize(bvh, node_index, cd_vert_node_offset, cd_face_node_offset);
return;
@@ -289,8 +289,8 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
*c2 = &bvh->nodes[children + 1];
c1->flag |= PBVH_Leaf;
c2->flag |= PBVH_Leaf;
- c1->bm_faces = BLI_gset_ptr_new_ex("bm_faces", BLI_gset_size(n->bm_faces) / 2);
- c2->bm_faces = BLI_gset_ptr_new_ex("bm_faces", BLI_gset_size(n->bm_faces) / 2);
+ c1->bm_faces = BLI_gset_ptr_new_ex("bm_faces", BLI_gset_len(n->bm_faces) / 2);
+ c2->bm_faces = BLI_gset_ptr_new_ex("bm_faces", BLI_gset_len(n->bm_faces) / 2);
/* Partition the parent node's faces between the two children */
GSET_ITER (gs_iter, n->bm_faces) {
@@ -305,11 +305,11 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
/* Enforce at least one primitive in each node */
GSet *empty = NULL, *other;
- if (BLI_gset_size(c1->bm_faces) == 0) {
+ if (BLI_gset_len(c1->bm_faces) == 0) {
empty = c1->bm_faces;
other = c2->bm_faces;
}
- else if (BLI_gset_size(c2->bm_faces) == 0) {
+ else if (BLI_gset_len(c2->bm_faces) == 0) {
empty = c2->bm_faces;
other = c1->bm_faces;
}
@@ -375,7 +375,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
{
GSet *bm_faces = bvh->nodes[node_index].bm_faces;
- const int bm_faces_size = BLI_gset_size(bm_faces);
+ const int bm_faces_size = BLI_gset_len(bm_faces);
if (bm_faces_size <= bvh->leaf_limit) {
/* Node limit not exceeded */
return false;
@@ -555,9 +555,9 @@ static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v)
#endif
#define pbvh_bmesh_node_vert_use_count_is_equal(bvh, node, v, n) \
- (pbvh_bmesh_node_vert_use_count_ex(bvh, node, v, (n) + 1) == n)
+ (pbvh_bmesh_node_vert_use_count_at_most(bvh, node, v, (n) + 1) == n)
-static int pbvh_bmesh_node_vert_use_count_ex(PBVH *bvh, PBVHNode *node, BMVert *v, const int count_max)
+static int pbvh_bmesh_node_vert_use_count_at_most(PBVH *bvh, PBVHNode *node, BMVert *v, const int count_max)
{
int count = 0;
BMFace *f;
@@ -1238,7 +1238,7 @@ static bool pbvh_bmesh_subdivide_long_edges(
bool any_subdivided = false;
while (!BLI_heap_is_empty(eq_ctx->q->heap)) {
- BMVert **pair = BLI_heap_popmin(eq_ctx->q->heap);
+ BMVert **pair = BLI_heap_pop_min(eq_ctx->q->heap);
BMVert *v1 = pair[0], *v2 = pair[1];
BMEdge *e;
@@ -1326,7 +1326,7 @@ static void pbvh_bmesh_collapse_edge(
/* Note: this could be done with BM_vert_splice(), but that
* requires handling other issues like duplicate edges, so doesn't
* really buy anything. */
- BLI_buffer_empty(deleted_faces);
+ BLI_buffer_clear(deleted_faces);
BMLoop *l;
@@ -1455,7 +1455,7 @@ static bool pbvh_bmesh_collapse_short_edges(
GHash *deleted_verts = BLI_ghash_ptr_new("deleted_verts");
while (!BLI_heap_is_empty(eq_ctx->q->heap)) {
- BMVert **pair = BLI_heap_popmin(eq_ctx->q->heap);
+ BMVert **pair = BLI_heap_pop_min(eq_ctx->q->heap);
BMVert *v1 = pair[0], *v2 = pair[1];
BLI_mempool_free(eq_ctx->pool, pair);
pair = NULL;
@@ -2011,10 +2011,10 @@ void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node)
if (node->bm_orco)
return;
- const int totvert = BLI_gset_size(node->bm_unique_verts) +
- BLI_gset_size(node->bm_other_verts);
+ const int totvert = BLI_gset_len(node->bm_unique_verts) +
+ BLI_gset_len(node->bm_other_verts);
- const int tottri = BLI_gset_size(node->bm_faces);
+ const int tottri = BLI_gset_len(node->bm_faces);
node->bm_orco = MEM_mallocN(sizeof(*node->bm_orco) * totvert, __func__);
node->bm_ortri = MEM_mallocN(sizeof(*node->bm_ortri) * tottri, __func__);
@@ -2189,12 +2189,12 @@ static void pbvh_bmesh_verify(PBVH *bvh)
int totface = 0, totvert = 0;
for (int i = 0; i < bvh->totnode; i++) {
PBVHNode *n = &bvh->nodes[i];
- totface += n->bm_faces ? BLI_gset_size(n->bm_faces) : 0;
- totvert += n->bm_unique_verts ? BLI_gset_size(n->bm_unique_verts) : 0;
+ totface += n->bm_faces ? BLI_gset_len(n->bm_faces) : 0;
+ totvert += n->bm_unique_verts ? BLI_gset_len(n->bm_unique_verts) : 0;
}
- BLI_assert(totface == BLI_gset_size(faces_all));
- BLI_assert(totvert == BLI_gset_size(verts_all));
+ BLI_assert(totface == BLI_gset_len(faces_all));
+ BLI_assert(totvert == BLI_gset_len(verts_all));
}
{
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index b794fcfd929..50314daa014 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -38,9 +38,10 @@
#include "DNA_ID.h"
#include "DNA_dynamicpaint_types.h"
+#include "DNA_group_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_particle_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
@@ -972,20 +973,20 @@ static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke
smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
- wt_density_grid = OpenVDB_export_grid_fl(writer, "density", dens, sds->res_wt, sds->fluidmat_wt, NULL);
+ wt_density_grid = OpenVDB_export_grid_fl(writer, "density", dens, sds->res_wt, sds->fluidmat_wt, sds->clipping, NULL);
clip_grid = wt_density_grid;
if (fluid_fields & SM_ACTIVE_FIRE) {
- OpenVDB_export_grid_fl(writer, "flame", flame, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
- OpenVDB_export_grid_fl(writer, "fuel", fuel, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
- OpenVDB_export_grid_fl(writer, "react", react, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
+ OpenVDB_export_grid_fl(writer, "flame", flame, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid);
+ OpenVDB_export_grid_fl(writer, "fuel", fuel, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid);
+ OpenVDB_export_grid_fl(writer, "react", react, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid);
}
if (fluid_fields & SM_ACTIVE_COLORS) {
- OpenVDB_export_grid_vec(writer, "color", r, g, b, sds->res_wt, sds->fluidmat_wt, VEC_INVARIANT, true, wt_density_grid);
+ OpenVDB_export_grid_vec(writer, "color", r, g, b, sds->res_wt, sds->fluidmat_wt, VEC_INVARIANT, true, sds->clipping, wt_density_grid);
}
- OpenVDB_export_grid_vec(writer, "texture coordinates", tcu, tcv, tcw, sds->res, sds->fluidmat, VEC_INVARIANT, false, wt_density_grid);
+ OpenVDB_export_grid_vec(writer, "texture coordinates", tcu, tcv, tcw, sds->res, sds->fluidmat, VEC_INVARIANT, false, sds->clipping, wt_density_grid);
}
if (sds->fluid) {
@@ -999,33 +1000,33 @@ static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke
OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dx", dx);
OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dt", dt);
- const char *name = (!sds->wt) ? "density" : "density low";
- density_grid = OpenVDB_export_grid_fl(writer, name, dens, sds->res, sds->fluidmat, NULL);
+ const char *name = (!sds->wt) ? "density" : "density_low";
+ density_grid = OpenVDB_export_grid_fl(writer, name, dens, sds->res, sds->fluidmat, sds->clipping, NULL);
clip_grid = sds->wt ? clip_grid : density_grid;
- OpenVDB_export_grid_fl(writer, "shadow", sds->shadow, sds->res, sds->fluidmat, NULL);
+ OpenVDB_export_grid_fl(writer, "shadow", sds->shadow, sds->res, sds->fluidmat, sds->clipping, NULL);
if (fluid_fields & SM_ACTIVE_HEAT) {
- OpenVDB_export_grid_fl(writer, "heat", heat, sds->res, sds->fluidmat, clip_grid);
- OpenVDB_export_grid_fl(writer, "heat old", heatold, sds->res, sds->fluidmat, clip_grid);
+ OpenVDB_export_grid_fl(writer, "heat", heat, sds->res, sds->fluidmat, sds->clipping, clip_grid);
+ OpenVDB_export_grid_fl(writer, "heat_old", heatold, sds->res, sds->fluidmat, sds->clipping, clip_grid);
}
if (fluid_fields & SM_ACTIVE_FIRE) {
- name = (!sds->wt) ? "flame" : "flame low";
- OpenVDB_export_grid_fl(writer, name, flame, sds->res, sds->fluidmat, density_grid);
- name = (!sds->wt) ? "fuel" : "fuel low";
- OpenVDB_export_grid_fl(writer, name, fuel, sds->res, sds->fluidmat, density_grid);
- name = (!sds->wt) ? "react" : "react low";
- OpenVDB_export_grid_fl(writer, name, react, sds->res, sds->fluidmat, density_grid);
+ name = (!sds->wt) ? "flame" : "flame_low";
+ OpenVDB_export_grid_fl(writer, name, flame, sds->res, sds->fluidmat, sds->clipping, density_grid);
+ name = (!sds->wt) ? "fuel" : "fuel_low";
+ OpenVDB_export_grid_fl(writer, name, fuel, sds->res, sds->fluidmat, sds->clipping, density_grid);
+ name = (!sds->wt) ? "react" : "react_low";
+ OpenVDB_export_grid_fl(writer, name, react, sds->res, sds->fluidmat, sds->clipping, density_grid);
}
if (fluid_fields & SM_ACTIVE_COLORS) {
- name = (!sds->wt) ? "color" : "color low";
- OpenVDB_export_grid_vec(writer, name, r, g, b, sds->res, sds->fluidmat, VEC_INVARIANT, true, density_grid);
+ name = (!sds->wt) ? "color" : "color_low";
+ OpenVDB_export_grid_vec(writer, name, r, g, b, sds->res, sds->fluidmat, VEC_INVARIANT, true, sds->clipping, density_grid);
}
- OpenVDB_export_grid_vec(writer, "velocity", vx, vy, vz, sds->res, sds->fluidmat, VEC_CONTRAVARIANT_RELATIVE, false, clip_grid);
- OpenVDB_export_grid_ch(writer, "obstacles", obstacles, sds->res, sds->fluidmat, NULL);
+ OpenVDB_export_grid_vec(writer, "velocity", vx, vy, vz, sds->res, sds->fluidmat, VEC_CONTRAVARIANT_RELATIVE, false, sds->clipping, clip_grid);
+ OpenVDB_export_grid_ch(writer, "obstacles", obstacles, sds->res, sds->fluidmat, sds->clipping, NULL);
}
return 1;
@@ -1104,25 +1105,25 @@ static int ptcache_smoke_openvdb_read(struct OpenVDBReader *reader, void *smoke_
OpenVDB_import_grid_fl(reader, "shadow", &sds->shadow, sds->res);
- const char *name = (!sds->wt) ? "density" : "density low";
+ const char *name = (!sds->wt) ? "density" : "density_low";
OpenVDB_import_grid_fl(reader, name, &dens, sds->res);
if (cache_fields & SM_ACTIVE_HEAT) {
OpenVDB_import_grid_fl(reader, "heat", &heat, sds->res);
- OpenVDB_import_grid_fl(reader, "heat old", &heatold, sds->res);
+ OpenVDB_import_grid_fl(reader, "heat_old", &heatold, sds->res);
}
if (cache_fields & SM_ACTIVE_FIRE) {
- name = (!sds->wt) ? "flame" : "flame low";
+ name = (!sds->wt) ? "flame" : "flame_low";
OpenVDB_import_grid_fl(reader, name, &flame, sds->res);
- name = (!sds->wt) ? "fuel" : "fuel low";
+ name = (!sds->wt) ? "fuel" : "fuel_low";
OpenVDB_import_grid_fl(reader, name, &fuel, sds->res);
- name = (!sds->wt) ? "react" : "react low";
+ name = (!sds->wt) ? "react" : "react_low";
OpenVDB_import_grid_fl(reader, name, &react, sds->res);
}
if (cache_fields & SM_ACTIVE_COLORS) {
- name = (!sds->wt) ? "color" : "color low";
+ name = (!sds->wt) ? "color" : "color_low";
OpenVDB_import_grid_vec(reader, name, &r, &g, &b, sds->res);
}
@@ -1646,6 +1647,25 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r
pid->file_type = PTCACHE_FILE_PTCACHE;
}
+PTCacheID BKE_ptcache_id_find(Object *ob, Scene *scene, PointCache *cache)
+{
+ PTCacheID result = {0};
+
+ ListBase pidlist;
+ BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
+
+ for (PTCacheID *pid = pidlist.first; pid; pid = pid->next) {
+ if (pid->cache == cache) {
+ result = *pid;
+ break;
+ }
+ }
+
+ BLI_freelistN(&pidlist);
+
+ return result;
+}
+
void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis)
{
PTCacheID *pid;
@@ -1714,22 +1734,19 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
BLI_addtail(lb, pid);
}
- if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) {
- ListBase *lb_dupli_ob;
- /* don't update the dupli groups, we only want their pid's */
- if ((lb_dupli_ob = object_duplilist_ex(G.main->eval_ctx, scene, ob, false))) {
- DupliObject *dob;
- for (dob= lb_dupli_ob->first; dob; dob= dob->next) {
- if (dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */
- ListBase lb_dupli_pid;
- BKE_ptcache_ids_from_object(&lb_dupli_pid, dob->ob, scene, duplis);
- BLI_movelisttolist(lb, &lb_dupli_pid);
- if (lb_dupli_pid.first)
- printf("Adding Dupli\n");
- }
- }
+ /* 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 && (duplis-- > 0) && (ob->dup_group)) {
+ Group *group = ob->dup_group;
+ Base *base = group->view_layer->object_bases.first;
- free_object_duplilist(lb_dupli_ob); /* does restore */
+ for (; base; base = base->next) {
+ if (base->object != ob) {
+ ListBase lb_dupli_pid;
+ BKE_ptcache_ids_from_object(&lb_dupli_pid, base->object, scene, duplis);
+ BLI_movelisttolist(lb, &lb_dupli_pid);
+ }
}
}
}
@@ -3662,7 +3679,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
stime = ptime = PIL_check_seconds_timer();
for (int fr = CFRA; fr <= endframe; fr += baker->quick_step, CFRA = fr) {
- BKE_scene_graph_update_for_newframe(G.main->eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
if (baker->update_progress) {
float progress = ((float)(CFRA - startframe)/(float)(endframe - startframe));
@@ -3748,7 +3765,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
CFRA = cfrao;
if (bake) { /* already on cfra unless baking */
- BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
}
/* TODO: call redraw all windows somehow */
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index bd4b817c8cd..ff521260993 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -50,7 +50,7 @@
#include "DNA_group_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
@@ -66,6 +66,8 @@
#include "BKE_rigidbody.h"
#include "BKE_scene.h"
+#include "DEG_depsgraph.h"
+
/* ************************************** */
/* Memory Management */
@@ -92,7 +94,7 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
if (rbw->physics_world) {
/* free physics references, we assume that all physics objects in will have been added to the world */
if (rbw->constraints) {
- FOREACH_GROUP_OBJECT(rbw->constraints, object)
+ FOREACH_GROUP_OBJECT_BEGIN(rbw->constraints, object)
{
if (object->rigidbody_constraint) {
RigidBodyCon *rbc = object->rigidbody_constraint;
@@ -101,11 +103,11 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
}
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
if (rbw->group) {
- FOREACH_GROUP_OBJECT(rbw->group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(rbw->group, object)
{
if (object->rigidbody_object) {
RigidBodyOb *rbo = object->rigidbody_object;
@@ -114,7 +116,7 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
}
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
/* free dynamics world */
RB_dworld_delete(rbw->physics_world);
@@ -702,6 +704,39 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool
/* --------------------- */
+static void rigidbody_constraint_set_limits(RigidBodyCon *rbc, void (*set_limits)(rbConstraint*,int,float,float))
+{
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X)
+ set_limits(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper);
+ else
+ set_limits(rbc->physics_constraint, RB_LIMIT_LIN_X, 0.0f, -1.0f);
+
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Y)
+ set_limits(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->limit_lin_y_lower, rbc->limit_lin_y_upper);
+ else
+ set_limits(rbc->physics_constraint, RB_LIMIT_LIN_Y, 0.0f, -1.0f);
+
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Z)
+ set_limits(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->limit_lin_z_lower, rbc->limit_lin_z_upper);
+ else
+ set_limits(rbc->physics_constraint, RB_LIMIT_LIN_Z, 0.0f, -1.0f);
+
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X)
+ set_limits(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->limit_ang_x_lower, rbc->limit_ang_x_upper);
+ else
+ set_limits(rbc->physics_constraint, RB_LIMIT_ANG_X, 0.0f, -1.0f);
+
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Y)
+ set_limits(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->limit_ang_y_lower, rbc->limit_ang_y_upper);
+ else
+ set_limits(rbc->physics_constraint, RB_LIMIT_ANG_Y, 0.0f, -1.0f);
+
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z)
+ set_limits(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->limit_ang_z_lower, rbc->limit_ang_z_upper);
+ else
+ set_limits(rbc->physics_constraint, RB_LIMIT_ANG_Z, 0.0f, -1.0f);
+}
+
/**
* Create physics sim representation of constraint given rigid body constraint settings
*
@@ -820,40 +855,13 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_damping_ang_z);
RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint);
- ATTR_FALLTHROUGH;
- case RBC_TYPE_6DOF:
- if (rbc->type == RBC_TYPE_6DOF) /* a litte awkward but avoids duplicate code for limits */
- rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2);
-
- if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X)
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper);
- else
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, 0.0f, -1.0f);
- if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Y)
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->limit_lin_y_lower, rbc->limit_lin_y_upper);
- else
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Y, 0.0f, -1.0f);
-
- if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Z)
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->limit_lin_z_lower, rbc->limit_lin_z_upper);
- else
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Z, 0.0f, -1.0f);
-
- if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X)
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->limit_ang_x_lower, rbc->limit_ang_x_upper);
- else
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_X, 0.0f, -1.0f);
-
- if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Y)
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->limit_ang_y_lower, rbc->limit_ang_y_upper);
- else
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Y, 0.0f, -1.0f);
+ rigidbody_constraint_set_limits(rbc, RB_constraint_set_limits_6dof_spring);
+ break;
+ case RBC_TYPE_6DOF:
+ rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2);
- if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z)
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->limit_ang_z_lower, rbc->limit_ang_z_upper);
- else
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, 0.0f, -1.0f);
+ rigidbody_constraint_set_limits(rbc, RB_constraint_set_limits_6dof);
break;
case RBC_TYPE_MOTOR:
rbc->physics_constraint = RB_constraint_new_motor(loc, rot, rb1, rb2);
@@ -1148,7 +1156,7 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
/* remove object from rigid body constraints */
if (rbw->constraints) {
- FOREACH_GROUP_OBJECT(rbw->constraints, obt)
+ FOREACH_GROUP_OBJECT_BEGIN(rbw->constraints, obt)
{
if (obt && obt->rigidbody_constraint) {
rbc = obt->rigidbody_constraint;
@@ -1157,7 +1165,7 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
}
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
}
@@ -1201,12 +1209,12 @@ static void rigidbody_update_ob_array(RigidBodyWorld *rbw)
}
i = 0;
- FOREACH_GROUP_OBJECT(rbw->group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(rbw->group, object)
{
rbw->objects[i] = object;
i++;
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw)
@@ -1332,7 +1340,7 @@ static void rigidbody_update_simulation(const struct EvaluationContext *eval_ctx
* Memory management needs redesign here, this is just a dirty workaround.
*/
if (rebuild && rbw->constraints) {
- FOREACH_GROUP_OBJECT(rbw->constraints, ob)
+ FOREACH_GROUP_OBJECT_BEGIN(rbw->constraints, ob)
{
RigidBodyCon *rbc = ob->rigidbody_constraint;
if (rbc && rbc->physics_constraint) {
@@ -1341,11 +1349,11 @@ static void rigidbody_update_simulation(const struct EvaluationContext *eval_ctx
rbc->physics_constraint = NULL;
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
/* update objects */
- FOREACH_GROUP_OBJECT(rbw->group, ob)
+ FOREACH_GROUP_OBJECT_BEGIN(rbw->group, ob)
{
if (ob->type == OB_MESH) {
/* validate that we've got valid object set up here... */
@@ -1388,13 +1396,13 @@ static void rigidbody_update_simulation(const struct EvaluationContext *eval_ctx
rigidbody_update_sim_ob(eval_ctx, scene, rbw, ob, rbo);
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
/* update constraints */
if (rbw->constraints == NULL) /* no constraints, move on */
return;
- FOREACH_GROUP_OBJECT(rbw->constraints, ob)
+ FOREACH_GROUP_OBJECT_BEGIN(rbw->constraints, ob)
{
/* validate that we've got valid object set up here... */
RigidBodyCon *rbc = ob->rigidbody_constraint;
@@ -1422,12 +1430,12 @@ static void rigidbody_update_simulation(const struct EvaluationContext *eval_ctx
rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE;
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw)
{
- FOREACH_GROUP_BASE(rbw->group, base)
+ FOREACH_GROUP_BASE_BEGIN(rbw->group, base)
{
Object *ob = base->object;
RigidBodyOb *rbo = ob->rigidbody_object;
@@ -1688,11 +1696,7 @@ void BKE_rigidbody_rebuild_sim(const struct EvaluationContext *eval_ctx,
Scene *scene)
{
float ctime = BKE_scene_frame_get(scene);
-
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s at %f\n", __func__, ctime);
- }
-
+ DEG_debug_print_eval_time(__func__, scene->id.name, scene, ctime);
/* rebuild sim data (i.e. after resetting to start of timeline) */
if (BKE_scene_check_rigidbody_active(scene)) {
BKE_rigidbody_rebuild_world(eval_ctx, scene, ctime);
@@ -1703,11 +1707,7 @@ void BKE_rigidbody_eval_simulation(const struct EvaluationContext *eval_ctx,
Scene *scene)
{
float ctime = BKE_scene_frame_get(scene);
-
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s at %f\n", __func__, ctime);
- }
-
+ DEG_debug_print_eval_time(__func__, scene->id.name, scene, ctime);
/* evaluate rigidbody sim */
if (BKE_scene_check_rigidbody_active(scene)) {
BKE_rigidbody_do_simulation(eval_ctx, scene, ctime);
@@ -1720,11 +1720,7 @@ void BKE_rigidbody_object_sync_transforms(const struct EvaluationContext *UNUSED
{
RigidBodyWorld *rbw = scene->rigidbody_world;
float ctime = BKE_scene_frame_get(scene);
-
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s\n", __func__, ob->id.name);
- }
-
+ DEG_debug_print_eval_time(__func__, ob->id.name, ob, ctime);
/* read values pushed into RBO from sim/cache... */
BKE_rigidbody_sync_transforms(rbw, ob, ctime);
}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 16e9844241d..9a7c10d31de 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -151,6 +151,83 @@ static void remove_sequencer_fcurves(Scene *sce)
}
}
+/* flag -- copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). */
+ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
+{
+ if (toolsettings == NULL) {
+ return NULL;
+ }
+ ToolSettings *ts = MEM_dupallocN(toolsettings);
+ if (ts->vpaint) {
+ ts->vpaint = MEM_dupallocN(ts->vpaint);
+ BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, flag);
+ }
+ if (ts->wpaint) {
+ ts->wpaint = MEM_dupallocN(ts->wpaint);
+ BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, flag);
+ }
+ if (ts->sculpt) {
+ ts->sculpt = MEM_dupallocN(ts->sculpt);
+ BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint, flag);
+ }
+ if (ts->uvsculpt) {
+ ts->uvsculpt = MEM_dupallocN(ts->uvsculpt);
+ BKE_paint_copy(&ts->uvsculpt->paint, &ts->uvsculpt->paint, flag);
+ }
+
+ BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag);
+ ts->imapaint.paintcursor = NULL;
+ ts->particle.paintcursor = NULL;
+ ts->particle.scene = NULL;
+ ts->particle.object = NULL;
+
+ /* duplicate Grease Pencil Drawing Brushes */
+ BLI_listbase_clear(&ts->gp_brushes);
+ for (bGPDbrush *brush = toolsettings->gp_brushes.first; brush; brush = brush->next) {
+ bGPDbrush *newbrush = BKE_gpencil_brush_duplicate(brush);
+ BLI_addtail(&ts->gp_brushes, newbrush);
+ }
+
+ /* duplicate Grease Pencil interpolation curve */
+ ts->gp_interpolate.custom_ipo = curvemapping_copy(ts->gp_interpolate.custom_ipo);
+ return ts;
+}
+
+void BKE_toolsettings_free(ToolSettings *toolsettings)
+{
+ if (toolsettings == NULL) {
+ return;
+ }
+ if (toolsettings->vpaint) {
+ BKE_paint_free(&toolsettings->vpaint->paint);
+ MEM_freeN(toolsettings->vpaint);
+ }
+ if (toolsettings->wpaint) {
+ BKE_paint_free(&toolsettings->wpaint->paint);
+ MEM_freeN(toolsettings->wpaint);
+ }
+ if (toolsettings->sculpt) {
+ BKE_paint_free(&toolsettings->sculpt->paint);
+ MEM_freeN(toolsettings->sculpt);
+ }
+ if (toolsettings->uvsculpt) {
+ BKE_paint_free(&toolsettings->uvsculpt->paint);
+ MEM_freeN(toolsettings->uvsculpt);
+ }
+ BKE_paint_free(&toolsettings->imapaint.paint);
+
+ /* free Grease Pencil Drawing Brushes */
+ BKE_gpencil_free_brushes(&toolsettings->gp_brushes);
+ BLI_freelistN(&toolsettings->gp_brushes);
+
+ /* free Grease Pencil interpolation curve */
+ if (toolsettings->gp_interpolate.custom_ipo) {
+ curvemapping_free(toolsettings->gp_interpolate.custom_ipo);
+ }
+
+ MEM_freeN(toolsettings);
+}
+
/**
* Only copy internal data of Scene ID from source to already allocated/initialized destination.
* You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
@@ -166,7 +243,6 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
sce_dst->ed = NULL;
sce_dst->depsgraph_hash = NULL;
- sce_dst->obedit = NULL;
sce_dst->fps_info = NULL;
/* layers and collections */
@@ -224,41 +300,7 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
curvemapping_copy_data(&sce_dst->r.mblur_shutter_curve, &sce_src->r.mblur_shutter_curve);
/* tool settings */
- if (sce_dst->toolsettings != NULL) {
- ToolSettings *ts = sce_dst->toolsettings = MEM_dupallocN(sce_dst->toolsettings);
- if (ts->vpaint) {
- ts->vpaint = MEM_dupallocN(ts->vpaint);
- BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, flag_subdata);
- }
- if (ts->wpaint) {
- ts->wpaint = MEM_dupallocN(ts->wpaint);
- BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, flag_subdata);
- }
- if (ts->sculpt) {
- ts->sculpt = MEM_dupallocN(ts->sculpt);
- BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint, flag_subdata);
- }
- if (ts->uvsculpt) {
- ts->uvsculpt = MEM_dupallocN(ts->uvsculpt);
- BKE_paint_copy(&ts->uvsculpt->paint, &ts->uvsculpt->paint, flag_subdata);
- }
-
- BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag_subdata);
- ts->imapaint.paintcursor = NULL;
- ts->particle.paintcursor = NULL;
- ts->particle.scene = NULL;
- ts->particle.object = NULL;
-
- /* duplicate Grease Pencil Drawing Brushes */
- BLI_listbase_clear(&ts->gp_brushes);
- for (bGPDbrush *brush = sce_src->toolsettings->gp_brushes.first; brush; brush = brush->next) {
- bGPDbrush *newbrush = BKE_gpencil_brush_duplicate(brush);
- BLI_addtail(&ts->gp_brushes, newbrush);
- }
-
- /* duplicate Grease Pencil interpolation curve */
- ts->gp_interpolate.custom_ipo = curvemapping_copy(ts->gp_interpolate.custom_ipo);
- }
+ sce_dst->toolsettings = BKE_toolsettings_copy(sce_dst->toolsettings, flag_subdata);
/* make a private copy of the avicodecdata */
if (sce_src->r.avicodecdata) {
@@ -297,7 +339,6 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
/* TODO this should/could most likely be replaced by call to more generic code at some point...
* But for now, let's keep it well isolated here. */
if (type == SCE_COPY_EMPTY) {
- ToolSettings *ts;
ListBase rv;
sce_copy = BKE_scene_add(bmain, sce->id.name + 2);
@@ -332,46 +373,7 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
curvemapping_copy_data(&sce_copy->r.mblur_shutter_curve, &sce->r.mblur_shutter_curve);
/* tool settings */
- sce_copy->toolsettings = MEM_dupallocN(sce->toolsettings);
-
- ts = sce_copy->toolsettings;
- if (ts) {
- if (ts->vpaint) {
- ts->vpaint = MEM_dupallocN(ts->vpaint);
- BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, 0);
- }
- if (ts->wpaint) {
- ts->wpaint = MEM_dupallocN(ts->wpaint);
- BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, 0);
- }
- if (ts->sculpt) {
- ts->sculpt = MEM_dupallocN(ts->sculpt);
- BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint, 0);
- }
- if (ts->uvsculpt) {
- ts->uvsculpt = MEM_dupallocN(ts->uvsculpt);
- BKE_paint_copy(&ts->uvsculpt->paint, &ts->uvsculpt->paint, 0);
- }
-
- BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, 0);
- ts->imapaint.paintcursor = NULL;
- id_us_plus((ID *)ts->imapaint.stencil);
- id_us_plus((ID *)ts->imapaint.clone);
- id_us_plus((ID *)ts->imapaint.canvas);
- ts->particle.paintcursor = NULL;
- ts->particle.scene = NULL;
- ts->particle.object = NULL;
-
- /* duplicate Grease Pencil Drawing Brushes */
- BLI_listbase_clear(&ts->gp_brushes);
- for (bGPDbrush *brush = sce->toolsettings->gp_brushes.first; brush; brush = brush->next) {
- bGPDbrush *newbrush = BKE_gpencil_brush_duplicate(brush);
- BLI_addtail(&ts->gp_brushes, newbrush);
- }
-
- /* duplicate Grease Pencil interpolation curve */
- ts->gp_interpolate.custom_ipo = curvemapping_copy(ts->gp_interpolate.custom_ipo);
- }
+ sce_copy->toolsettings = BKE_toolsettings_copy(sce->toolsettings, 0);
/* make a private copy of the avicodecdata */
if (sce->r.avicodecdata) {
@@ -493,37 +495,8 @@ void BKE_scene_free_ex(Scene *sce, const bool do_id_user)
BLI_freelistN(&sce->markers);
BLI_freelistN(&sce->r.views);
- if (sce->toolsettings) {
- if (sce->toolsettings->vpaint) {
- BKE_paint_free(&sce->toolsettings->vpaint->paint);
- MEM_freeN(sce->toolsettings->vpaint);
- }
- if (sce->toolsettings->wpaint) {
- BKE_paint_free(&sce->toolsettings->wpaint->paint);
- MEM_freeN(sce->toolsettings->wpaint);
- }
- if (sce->toolsettings->sculpt) {
- BKE_paint_free(&sce->toolsettings->sculpt->paint);
- MEM_freeN(sce->toolsettings->sculpt);
- }
- if (sce->toolsettings->uvsculpt) {
- BKE_paint_free(&sce->toolsettings->uvsculpt->paint);
- MEM_freeN(sce->toolsettings->uvsculpt);
- }
- BKE_paint_free(&sce->toolsettings->imapaint.paint);
-
- /* free Grease Pencil Drawing Brushes */
- BKE_gpencil_free_brushes(&sce->toolsettings->gp_brushes);
- BLI_freelistN(&sce->toolsettings->gp_brushes);
-
- /* free Grease Pencil interpolation curve */
- if (sce->toolsettings->gp_interpolate.custom_ipo) {
- curvemapping_free(sce->toolsettings->gp_interpolate.custom_ipo);
- }
-
- MEM_freeN(sce->toolsettings);
- sce->toolsettings = NULL;
- }
+ BKE_toolsettings_free(sce->toolsettings);
+ sce->toolsettings = NULL;
BKE_scene_free_depsgraph_hash(sce);
@@ -618,7 +591,7 @@ void BKE_scene_init(Scene *sce)
*/
sce->r.color_mgt_flag |= R_COLOR_MANAGEMENT;
- sce->r.gauss = 1.0;
+ sce->r.gauss = 1.5f;
/* deprecated but keep for upwards compat */
sce->r.postgamma = 1.0;
@@ -982,21 +955,17 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
/* check for cyclic sets, for reading old files but also for definite security (py?) */
BKE_scene_validate_setscene(bmain, scene);
- /* can happen when switching modes in other scenes */
- if (scene->obedit && !(scene->obedit->mode & OB_MODE_EDIT))
- scene->obedit = NULL;
-
/* deselect objects (for dataselect) */
for (ob = bmain->object.first; ob; ob = ob->id.next)
ob->flag &= ~(SELECT | OB_FROMGROUP);
/* group flags again */
for (group = bmain->group.first; group; group = group->id.next) {
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
object->flag |= OB_FROMGROUP;
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
/* copy layers and flags from bases to objects */
@@ -1381,7 +1350,10 @@ static bool check_rendered_viewport_visible(Main *bmain)
return false;
}
-static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
+/* TODO(campbell): shouldn't we be able to use 'eval_ctx->view_layer' here?
+ * Currently this is NULL on load, so don't. */
+static void prepare_mesh_for_viewport_render(
+ Main *bmain, const ViewLayer *view_layer)
{
/* This is needed to prepare mesh to be used by the render
* engine from the viewport rendering. We do loading here
@@ -1392,7 +1364,7 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
* call loading of the edit data for the mesh objects.
*/
- Object *obedit = scene->obedit;
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
if (obedit) {
Mesh *mesh = obedit->data;
if ((obedit->type == OB_MESH) &&
@@ -1401,7 +1373,11 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
{
if (check_rendered_viewport_visible(bmain)) {
BMesh *bm = mesh->edit_btmesh->bm;
- BM_mesh_bm_to_me(bm, mesh, (&(struct BMeshToMeshParams){0}));
+ BM_mesh_bm_to_me(
+ bm, mesh,
+ (&(struct BMeshToMeshParams){
+ .calc_object_remap = true,
+ }));
DEG_id_tag_update(&mesh->id, 0);
}
}
@@ -1411,17 +1387,12 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
/* TODO(sergey): This actually should become view_layer_graph or so.
* Same applies to update_for_newframe.
*/
-void BKE_scene_graph_update_tagged(EvaluationContext *eval_ctx,
- Depsgraph *depsgraph,
- Main *bmain,
- Scene *scene,
- ViewLayer *view_layer)
+void BKE_scene_graph_update_tagged(Depsgraph *depsgraph,
+ Main *bmain)
{
- /* TODO(sergey): Temporary solution for until pipeline.c is ported. */
- if (view_layer == NULL) {
- view_layer = DEG_get_evaluated_view_layer(depsgraph);
- BLI_assert(view_layer != NULL);
- }
+ Scene *scene = DEG_get_input_scene(depsgraph);
+ ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
+
/* TODO(sergey): Some functions here are changing global state,
* for example, clearing update tags from bmain.
*/
@@ -1430,13 +1401,13 @@ void BKE_scene_graph_update_tagged(EvaluationContext *eval_ctx,
/* Uncomment this to check if graph was properly tagged for update. */
// DEG_debug_graph_relations_validate(depsgraph, bmain, scene);
/* Flush editing data if needed. */
- prepare_mesh_for_viewport_render(bmain, scene);
+ prepare_mesh_for_viewport_render(bmain, view_layer);
/* Flush recalc flags to dependencies. */
DEG_graph_flush_update(bmain, depsgraph);
/* Update all objects: drivers, matrices, displists, etc. flags set
* by depgraph or manual, no layer check here, gets correct flushed.
*/
- DEG_evaluate_on_refresh(eval_ctx, depsgraph);
+ DEG_evaluate_on_refresh(depsgraph);
/* Update sound system animation (TODO, move to depsgraph). */
BKE_sound_update_scene(bmain, scene);
/* Inform editors about possible changes. */
@@ -1446,17 +1417,12 @@ void BKE_scene_graph_update_tagged(EvaluationContext *eval_ctx,
}
/* applies changes right away, does all sets too */
-void BKE_scene_graph_update_for_newframe(EvaluationContext *eval_ctx,
- Depsgraph *depsgraph,
- Main *bmain,
- Scene *scene,
- ViewLayer *view_layer)
+void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph,
+ Main *bmain)
{
- /* TODO(sergey): Temporary solution for until pipeline.c is ported. */
- if (view_layer == NULL) {
- view_layer = DEG_get_evaluated_view_layer(depsgraph);
- BLI_assert(view_layer != NULL);
- }
+ Scene *scene = DEG_get_input_scene(depsgraph);
+ ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
+
/* TODO(sergey): Some functions here are changing global state,
* for example, clearing update tags from bmain.
*/
@@ -1481,7 +1447,7 @@ void BKE_scene_graph_update_for_newframe(EvaluationContext *eval_ctx,
/* Update all objects: drivers, matrices, displists, etc. flags set
* by depgraph or manual, no layer check here, gets correct flushed.
*/
- DEG_evaluate_on_framechange(eval_ctx, bmain, depsgraph, ctime);
+ DEG_evaluate_on_framechange(bmain, depsgraph, ctime);
/* Update sound system animation (TODO, move to depsgraph). */
BKE_sound_update_scene(bmain, scene);
/* Notify editors and python about recalc. */
@@ -2222,7 +2188,7 @@ Depsgraph *BKE_scene_get_depsgraph(Scene *scene,
{
*key_ptr = MEM_mallocN(sizeof(DepsgraphKey), __func__);
**key_ptr = key;
- *depsgraph_ptr = DEG_graph_new();
+ *depsgraph_ptr = DEG_graph_new(scene, view_layer, DAG_EVAL_VIEWPORT);
}
depsgraph = *depsgraph_ptr;
}
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 754f59d2e33..c1b3a4ae0c8 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -39,8 +39,6 @@
#include "MEM_guardedalloc.h"
-#include "GPU_compositing.h"
-
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -182,7 +180,7 @@ ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar)
BLI_listbase_clear(&newar->panels_category);
BLI_listbase_clear(&newar->panels_category_active);
BLI_listbase_clear(&newar->ui_lists);
- newar->swinid = 0;
+ newar->visible = 0;
newar->manipulator_map = NULL;
newar->regiontimer = NULL;
newar->headerstr = NULL;
@@ -684,29 +682,6 @@ float BKE_screen_view3d_zoom_from_fac(float zoomfac)
return ((sqrtf(4.0f * zoomfac) - (float)M_SQRT2) * 50.0f);
}
-void BKE_screen_gpu_fx_validate(GPUFXSettings *fx_settings)
-{
- /* currently we use DOF from the camera _only_,
- * so we never allocate this, only copy from the Camera */
-#if 0
- if ((fx_settings->dof == NULL) &&
- (fx_settings->fx_flag & GPU_FX_FLAG_DOF))
- {
- GPUDOFSettings *fx_dof;
- fx_dof = fx_settings->dof = MEM_callocN(sizeof(GPUDOFSettings), __func__);
- }
-#endif
-
- if ((fx_settings->ssao == NULL) &&
- (fx_settings->fx_flag & GPU_FX_FLAG_SSAO))
- {
- GPUSSAOSettings *fx_ssao;
- fx_ssao = fx_settings->ssao = MEM_callocN(sizeof(GPUSSAOSettings), __func__);
-
- GPU_fx_compositor_init_ssao_settings(fx_ssao);
- }
-}
-
bool BKE_screen_is_fullscreen_area(const bScreen *screen)
{
return ELEM(screen->state, SCREENMAXIMIZED, SCREENFULL);
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index ee80438db64..49f120de250 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -52,6 +52,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "IMB_colormanagement.h"
+#include "IMB_metadata.h"
#include "BLI_math_color_blend.h"
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 424f4269f3c..58b83a754d8 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -86,6 +86,7 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_colormanagement.h"
+#include "IMB_metadata.h"
#include "BKE_context.h"
#include "BKE_sound.h"
@@ -946,6 +947,8 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_r
return;
}
+ IMB_anim_load_metadata(sanim->anim);
+
seq->len = IMB_anim_get_duration(sanim->anim, seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN);
seq->anim_preseek = IMB_anim_get_preseek(sanim->anim);
@@ -1680,6 +1683,11 @@ static bool seq_proxy_get_fname(Editing *ed, Sequence *seq, int cfra, int render
else if (seq->type == SEQ_TYPE_IMAGE) {
fname[0] = 0;
}
+ else {
+ /* We could make a name here, except non-movie's don't generate proxies,
+ * cancel until other types of sequence strips are supported. */
+ return false;
+ }
BLI_path_append(dir, sizeof(dir), fname);
BLI_path_abs(name, G.main->name);
}
@@ -2954,7 +2962,7 @@ static ImBuf *seq_render_movie_strip(const SeqRenderData *context, Sequence *seq
int totviews;
int i;
- if (totfiles != BLI_listbase_count_ex(&seq->anims, totfiles + 1))
+ if (totfiles != BLI_listbase_count_at_most(&seq->anims, totfiles + 1))
goto monoview_movie;
totviews = BKE_scene_multiview_num_views_get(&context->scene->r);
@@ -3264,9 +3272,10 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
// have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first); /* UNUSED */
have_comp = (scene->r.scemode & R_DOCOMP) && scene->use_nodes && scene->nodetree;
- /* Get depsgraph and scene layer for the strip. */
+ /* Get view layer for the strip. */
ViewLayer *view_layer = BKE_view_layer_from_scene_get(scene);
- Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ /* Depsgraph will be NULL when doing rendering. */
+ Depsgraph *depsgraph = NULL;
orig_data.scemode = scene->r.scemode;
orig_data.cfra = scene->r.cfra;
@@ -3323,14 +3332,16 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
context->scene->r.seq_prev_type = 3 /* == OB_SOLID */;
/* opengl offscreen render */
- context->eval_ctx->engine_type = RE_engines_find(scene->view_render.engine_id);
- BKE_scene_graph_update_for_newframe(context->eval_ctx, depsgraph, context->bmain, scene, view_layer);
+ RenderEngineType *engine_type = RE_engines_find(scene->view_render.engine_id);
+ depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ BKE_scene_graph_update_for_newframe(depsgraph, context->bmain);
ibuf = sequencer_view3d_cb(
/* set for OpenGL render (NULL when scrubbing) */
- context->eval_ctx, scene, view_layer, camera, width, height, IB_rect,
+ context->eval_ctx, scene, view_layer, engine_type,
+ camera, width, height, IB_rect,
draw_flags, context->scene->r.seq_prev_type,
scene->r.alphamode, context->gpu_samples, viewname,
- context->gpu_fx, context->gpu_offscreen, err_out);
+ context->gpu_offscreen, err_out);
if (ibuf == NULL) {
fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out);
}
@@ -3355,15 +3366,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
if (re == NULL)
re = RE_NewSceneRender(scene);
- /* NOTE: Without this tag rendering from command line fails.
- * TODO(sergey): Need some proper solution with ported
- * BKE_scene_set_background() or DEG_on_visible_change() ?
- */
- RE_SetDepsgraph(re, depsgraph);
- DEG_graph_id_tag_update(context->bmain, depsgraph, &scene->id, 0);
-
- BKE_scene_graph_update_for_newframe(context->eval_ctx, depsgraph, context->bmain, scene, view_layer);
- RE_BlenderFrame(re, context->bmain, scene, NULL, camera, scene->lay, frame, false);
+ RE_BlenderFrame(re, context->bmain, scene, view_layer, camera, scene->lay, frame, false);
/* restore previous state after it was toggled on & off by RE_BlenderFrame */
G.is_rendering = is_rendering;
@@ -3421,8 +3424,8 @@ finally:
scene->r.cfra = orig_data.cfra;
scene->r.subframe = orig_data.subframe;
- if (is_frame_update) {
- BKE_scene_graph_update_for_newframe(context->eval_ctx, depsgraph, context->bmain, scene, view_layer);
+ if (is_frame_update && (depsgraph != NULL)) {
+ BKE_scene_graph_update_for_newframe(depsgraph, context->bmain);
}
#ifdef DURIAN_CAMERA_SWITCH
@@ -5167,6 +5170,40 @@ void BKE_sequence_init_colorspace(Sequence *seq)
}
}
+float BKE_sequence_get_fps(Scene *scene, Sequence *seq)
+{
+ switch (seq->type) {
+ case SEQ_TYPE_MOVIE:
+ {
+ seq_open_anim_file(scene, seq, true);
+ if (BLI_listbase_is_empty(&seq->anims)) {
+ return 0.0f;
+ }
+ StripAnim *strip_anim = seq->anims.first;
+ if (strip_anim->anim == NULL) {
+ return 0.0f;
+ }
+ short frs_sec;
+ float frs_sec_base;
+ if (IMB_anim_get_fps(strip_anim->anim, &frs_sec, &frs_sec_base, true)) {
+ return (float)frs_sec / frs_sec_base;
+ }
+ break;
+ }
+ case SEQ_TYPE_MOVIECLIP:
+ if (seq->clip != NULL) {
+ return BKE_movieclip_get_fps(seq->clip);
+ }
+ break;
+ case SEQ_TYPE_SCENE:
+ if (seq->scene != NULL) {
+ return (float)seq->scene->r.frs_sec / seq->scene->r.frs_sec_base;
+ }
+ break;
+ }
+ return 0.0f;
+}
+
/* NOTE: this function doesn't fill in image names */
Sequence *BKE_sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
{
@@ -5359,6 +5396,8 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad
}
}
+ IMB_anim_load_metadata(anim_arr[0]);
+
seq->anim_preseek = IMB_anim_get_preseek(anim_arr[0]);
BLI_strncpy(seq->name + 2, "Movie", SEQ_NAME_MAXSTR - 2);
BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index 9f9818127bc..9215d56eb30 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -72,7 +72,6 @@
#include "BKE_customdata.h"
#include "BKE_deform.h"
#include "BKE_DerivedMesh.h"
-#include "BKE_global.h"
#include "BKE_effect.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
@@ -170,11 +169,11 @@ void smoke_reallocate_highres_fluid(SmokeDomainSettings *sds, float dx, int res[
}
/* smoke_turbulence_init uses non-threadsafe functions from fftw3 lib (like fftw_plan & co). */
- BLI_lock_thread(LOCK_FFTW);
+ BLI_thread_lock(LOCK_FFTW);
sds->wt = smoke_turbulence_init(res, sds->amplify + 1, sds->noise, BKE_tempdir_session(), use_fire, use_colors);
- BLI_unlock_thread(LOCK_FFTW);
+ BLI_thread_unlock(LOCK_FFTW);
sds->res_wt[0] = res[0] * (sds->amplify + 1);
sds->res_wt[1] = res[1] * (sds->amplify + 1);
@@ -525,8 +524,8 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->domain->burning_rate = 0.75f;
smd->domain->flame_smoke = 1.0f;
smd->domain->flame_vorticity = 0.5f;
- smd->domain->flame_ignition = 1.25f;
- smd->domain->flame_max_temp = 1.75f;
+ smd->domain->flame_ignition = 1.5f;
+ smd->domain->flame_max_temp = 3.0f;
/* color */
smd->domain->flame_smoke_color[0] = 0.7f;
smd->domain->flame_smoke_color[1] = 0.7f;
@@ -553,6 +552,8 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->domain->coba = NULL;
smd->domain->coba_field = FLUID_FIELD_DENSITY;
+
+ smd->domain->clipping = 1e-3f;
}
else if (smd->type & MOD_SMOKE_TYPE_FLOW)
{
@@ -1287,6 +1288,8 @@ static void emit_from_particles(
curvemapping_changed_all(psys->part->clumpcurve);
if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve)
curvemapping_changed_all(psys->part->roughcurve);
+ if ((psys->part->child_flag & PART_CHILD_USE_TWIST_CURVE) && psys->part->twistcurve)
+ curvemapping_changed_all(psys->part->twistcurve);
/* initialize particle cache */
if (psys->part->type == PART_HAIR) {
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 3cfa8787f4b..1fb95bd3115 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -1580,12 +1580,12 @@ static void sb_sfesf_threads_run(const struct EvaluationContext *eval_ctx, Scene
sb_threads[i].tot= totthread;
}
if (totthread > 1) {
- BLI_init_threads(&threads, exec_scan_for_ext_spring_forces, totthread);
+ BLI_threadpool_init(&threads, exec_scan_for_ext_spring_forces, totthread);
for (i=0; i<totthread; i++)
- BLI_insert_thread(&threads, &sb_threads[i]);
+ BLI_threadpool_insert(&threads, &sb_threads[i]);
- BLI_end_threads(&threads);
+ BLI_threadpool_end(&threads);
}
else
exec_scan_for_ext_spring_forces(&sb_threads[0]);
@@ -2192,12 +2192,12 @@ static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float t
if (totthread > 1) {
- BLI_init_threads(&threads, exec_softbody_calc_forces, totthread);
+ BLI_threadpool_init(&threads, exec_softbody_calc_forces, totthread);
for (i=0; i<totthread; i++)
- BLI_insert_thread(&threads, &sb_threads[i]);
+ BLI_threadpool_insert(&threads, &sb_threads[i]);
- BLI_end_threads(&threads);
+ BLI_threadpool_end(&threads);
}
else
exec_softbody_calc_forces(&sb_threads[0]);
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index 9d604a9382a..1d2e12f34ac 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -32,7 +32,6 @@
#include "BLI_utildefines.h"
#include "BKE_animsys.h"
-#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 1c3ff352126..9280341b4e4 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -361,7 +361,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
#ifdef USE_DYNSIZE
CCGVertHDL fverts[nverts];
#else
- BLI_array_empty(fverts);
+ BLI_array_clear(fverts);
BLI_array_grow_items(fverts, nverts);
#endif
@@ -400,7 +400,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
#ifdef USE_DYNSIZE
CCGVertHDL fverts[nverts];
#else
- BLI_array_empty(fverts);
+ BLI_array_clear(fverts);
BLI_array_grow_items(fverts, nverts);
#endif
@@ -744,7 +744,7 @@ static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss,
#ifdef USE_DYNSIZE
CCGVertHDL fVerts[mp->totloop];
#else
- BLI_array_empty(fVerts);
+ BLI_array_clear(fVerts);
BLI_array_grow_items(fVerts, mp->totloop);
#endif
@@ -4583,7 +4583,7 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
*((int *)ccgSubSurf_getFaceUserData(ss, f)) = vertNum;
#ifndef USE_DYNSIZE
- BLI_array_empty(loopidx);
+ BLI_array_clear(loopidx);
BLI_array_grow_items(loopidx, numVerts);
#endif
for (s = 0; s < numVerts; s++) {
@@ -4591,7 +4591,7 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
}
#ifndef USE_DYNSIZE
- BLI_array_empty(vertidx);
+ BLI_array_clear(vertidx);
BLI_array_grow_items(vertidx, numVerts);
#endif
for (s = 0; s < numVerts; s++) {
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 4ae9818f891..cd9b8ae339d 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -120,13 +120,56 @@
*
*/
+
+/* Undo opcodes */
+
+enum {
+ /* Complex editing */
+ /* 1 - opcode is followed by 1 byte for ascii character and opcode (repeat)) */
+ /* 2 - opcode is followed by 2 bytes for utf-8 character and opcode (repeat)) */
+ /* 3 - opcode is followed by 3 bytes for utf-8 character and opcode (repeat)) */
+ /* 4 - opcode is followed by 4 bytes for unicode character and opcode (repeat)) */
+ UNDO_INSERT_1 = 013,
+ UNDO_INSERT_2 = 014,
+ UNDO_INSERT_3 = 015,
+ UNDO_INSERT_4 = 016,
+
+ UNDO_BS_1 = 017,
+ UNDO_BS_2 = 020,
+ UNDO_BS_3 = 021,
+ UNDO_BS_4 = 022,
+
+ UNDO_DEL_1 = 023,
+ UNDO_DEL_2 = 024,
+ UNDO_DEL_3 = 025,
+ UNDO_DEL_4 = 026,
+
+ /* Text block (opcode is followed
+ * by 4 character length ID + the text
+ * block itself + the 4 character length
+ * ID (repeat) and opcode (repeat)) */
+ UNDO_DBLOCK = 027, /* Delete block */
+ UNDO_IBLOCK = 030, /* Insert block */
+
+ /* Misc */
+ UNDO_INDENT = 032,
+ UNDO_UNINDENT = 033,
+ UNDO_COMMENT = 034,
+ UNDO_UNCOMMENT = 035,
+
+ UNDO_MOVE_LINES_UP = 036,
+ UNDO_MOVE_LINES_DOWN = 037,
+
+ UNDO_DUPLICATE = 040,
+};
+
/***/
static void txt_pop_first(Text *text);
static void txt_pop_last(Text *text);
-static void txt_undo_add_blockop(Text *text, int op, const char *buf);
+static void txt_undo_add_blockop(Text *text, TextUndoBuf *utxt, int op, const char *buf);
static void txt_delete_line(Text *text, TextLine *line);
-static void txt_delete_sel(Text *text);
+static void txt_delete_sel(Text *text, TextUndoBuf *utxt);
static void txt_make_dirty(Text *text);
/***/
@@ -144,13 +187,6 @@ int txt_get_undostate(void)
return undoing;
}
-static void init_undo_text(Text *text)
-{
- text->undo_pos = -1;
- text->undo_len = TXT_INIT_UNDO;
- text->undo_buf = MEM_mallocN(text->undo_len, "undo buf");
-}
-
/**
* \note caller must handle `undo_buf` and `compiled` members.
*/
@@ -178,7 +214,6 @@ void BKE_text_free(Text *text)
BKE_text_free_lines(text);
MEM_SAFE_FREE(text->name);
- MEM_SAFE_FREE(text->undo_buf);
#ifdef WITH_PYTHON
BPY_text_free_code(text);
#endif
@@ -192,8 +227,6 @@ void BKE_text_init(Text *ta)
ta->name = NULL;
- init_undo_text(ta);
-
ta->nlines = 1;
ta->flags = TXT_ISDIRTY | TXT_ISMEM;
if ((U.flag & USER_TXT_TABSTOSPACES_DISABLE) == 0)
@@ -375,10 +408,6 @@ bool BKE_text_reload(Text *text)
txt_make_dirty(text);
/* clear undo buffer */
- MEM_freeN(text->undo_buf);
- init_undo_text(text);
-
-
if (BLI_stat(filepath_abs, &st) != -1) {
text->mtime = st.st_mtime;
}
@@ -427,8 +456,6 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const
}
/* clear undo buffer */
- init_undo_text(ta);
-
if (BLI_stat(filepath_abs, &st) != -1) {
ta->mtime = st.st_mtime;
}
@@ -482,8 +509,6 @@ void BKE_text_copy_data(Main *UNUSED(bmain), Text *ta_dst, const Text *ta_src, c
ta_dst->curl = ta_dst->sell = ta_dst->lines.first;
ta_dst->curc = ta_dst->selc = 0;
-
- init_undo_text(ta_dst);
}
Text *BKE_text_copy(Main *bmain, const Text *ta)
@@ -498,25 +523,29 @@ void BKE_text_make_local(Main *bmain, Text *text, const bool lib_local)
BKE_id_make_local_generic(bmain, &text->id, true, lib_local);
}
-void BKE_text_clear(Text *text) /* called directly from rna */
+void BKE_text_clear(Text *text, TextUndoBuf *utxt) /* called directly from rna */
{
int oldstate;
- oldstate = txt_get_undostate();
- txt_set_undostate(1);
+ if (utxt) {
+ oldstate = txt_get_undostate();
+ }
+ txt_set_undostate(utxt != NULL);
+
txt_sel_all(text);
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
+
txt_set_undostate(oldstate);
txt_make_dirty(text);
}
-void BKE_text_write(Text *text, const char *str) /* called directly from rna */
+void BKE_text_write(Text *text, TextUndoBuf *utxt, const char *str) /* called directly from rna */
{
int oldstate;
oldstate = txt_get_undostate();
- txt_insert_buf(text, str);
+ txt_insert_buf(text, utxt, str);
txt_move_eof(text, 0);
txt_set_undostate(oldstate);
@@ -1109,7 +1138,7 @@ bool txt_has_sel(Text *text)
return ((text->curl != text->sell) || (text->curc != text->selc));
}
-static void txt_delete_sel(Text *text)
+static void txt_delete_sel(Text *text, TextUndoBuf *utxt)
{
TextLine *tmpl;
char *buf;
@@ -1123,7 +1152,7 @@ static void txt_delete_sel(Text *text)
if (!undoing) {
buf = txt_sel_to_buf(text);
- txt_undo_add_blockop(text, UNDO_DBLOCK, buf);
+ txt_undo_add_blockop(text, utxt, UNDO_DBLOCK, buf);
MEM_freeN(buf);
}
@@ -1364,7 +1393,7 @@ char *txt_sel_to_buf(Text *text)
return buf;
}
-void txt_insert_buf(Text *text, const char *in_buffer)
+void txt_insert_buf(Text *text, TextUndoBuf *utxt, const char *in_buffer)
{
int l = 0, u, len;
size_t i = 0, j;
@@ -1373,22 +1402,22 @@ void txt_insert_buf(Text *text, const char *in_buffer)
if (!in_buffer) return;
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
len = strlen(in_buffer);
buffer = BLI_strdupn(in_buffer, len);
len += txt_extended_ascii_as_utf8(&buffer);
- if (!undoing) txt_undo_add_blockop(text, UNDO_IBLOCK, buffer);
+ if (!undoing) txt_undo_add_blockop(text, utxt, UNDO_IBLOCK, buffer);
u = undoing;
undoing = 1;
/* Read the first line (or as close as possible */
while (buffer[i] && buffer[i] != '\n')
- txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &i));
+ txt_add_raw_char(text, utxt, BLI_str_utf8_as_unicode_step(buffer, &i));
- if (buffer[i] == '\n') txt_split_curline(text);
+ if (buffer[i] == '\n') txt_split_curline(text, utxt);
else { undoing = u; MEM_freeN(buffer); return; }
i++;
@@ -1406,7 +1435,7 @@ void txt_insert_buf(Text *text, const char *in_buffer)
}
else {
for (j = i - l; j < i && j < len; )
- txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &j));
+ txt_add_raw_char(text, utxt, BLI_str_utf8_as_unicode_step(buffer, &j));
break;
}
}
@@ -1420,33 +1449,47 @@ void txt_insert_buf(Text *text, const char *in_buffer)
/* Undo functions */
/******************/
-static bool max_undo_test(Text *text, int x)
+static bool max_undo_test(TextUndoBuf *utxt, int x)
{
- while (text->undo_pos + x >= text->undo_len) {
- if (text->undo_len * 2 > TXT_MAX_UNDO) {
- /* XXX error("Undo limit reached, buffer cleared\n"); */
- MEM_freeN(text->undo_buf);
- init_undo_text(text);
- return false;
- }
- else {
- void *tmp = text->undo_buf;
- text->undo_buf = MEM_callocN(text->undo_len * 2, "undo buf");
- memcpy(text->undo_buf, tmp, text->undo_len);
- text->undo_len *= 2;
- MEM_freeN(tmp);
- }
- }
+ /* Normally over-allocating is preferred,
+ * however in this case the buffer is small enough and re-allocation
+ * fast enough for each undo step that it's not a problem to allocate each time.
+ * This also saves on some memory when we have many text buffers
+ * that would have an empty undo memory allocated.
+ */
+ /* Add one for the null terminator. */
+ utxt->len = utxt->pos + x + 1;
+ if (utxt->len > TXT_MAX_UNDO) {
+ /* XXX error("Undo limit reached, buffer cleared\n"); */
+ MEM_freeN(utxt->buf);
+ return false;
+ }
+ else {
+ /* Small reallocations on each undo step is fine. */
+ utxt->buf = MEM_recallocN(utxt->buf, utxt->len);
+ }
return true;
}
+static void txt_undo_end(Text *UNUSED(text), TextUndoBuf *utxt)
+{
+ int undo_pos_end = utxt->pos + 1;
+ BLI_assert(undo_pos_end + 1 == utxt->len);
+ utxt->buf[undo_pos_end] = '\0';
+}
+
+/* Call once undo is done. */
+#ifndef NDEBUG
+
+#endif
+
#if 0 /* UNUSED */
-static void dump_buffer(Text *text)
+static void dump_buffer(TextUndoBuf *utxt)
{
int i = 0;
-
- while (i++ < text->undo_pos) printf("%d: %d %c\n", i, text->undo_buf[i], text->undo_buf[i]);
+
+ while (i++ < utxt->undo_pos) printf("%d: %d %c\n", i, utxt->buf[i], utxt->buf[i]);
}
/* Note: this function is outdated and must be updated if needed for future use */
@@ -1461,10 +1504,10 @@ void txt_print_undo(Text *text)
printf("---< Undo Buffer >---\n");
- printf("UndoPosition is %d\n", text->undo_pos);
+ printf("UndoPosition is %d\n", utxt->pos);
- while (i <= text->undo_pos) {
- op = text->undo_buf[i];
+ while (i <= utxt->pos) {
+ op = utxt->buf[i];
if (op == UNDO_INSERT_1) {
ops = "Insert ascii ";
@@ -1530,15 +1573,15 @@ void txt_print_undo(Text *text)
printf(" - Char is ");
switch (op) {
case UNDO_INSERT_1: case UNDO_BS_1: case UNDO_DEL_1:
- printf("%c", text->undo_buf[i]);
+ printf("%c", utxt->buf[i]);
i++;
break;
case UNDO_INSERT_2: case UNDO_BS_2: case UNDO_DEL_2:
- printf("%c%c", text->undo_buf[i], text->undo_buf[i + 1]);
+ printf("%c%c", utxt->buf[i], utxt->buf[i + 1]);
i += 2;
break;
case UNDO_INSERT_3: case UNDO_BS_3: case UNDO_DEL_3:
- printf("%c%c%c", text->undo_buf[i], text->undo_buf[i + 1], text->undo_buf[i + 2]);
+ printf("%c%c%c", utxt->buf[i], utxt->buf[i + 1], utxt->buf[i + 2]);
i += 3;
break;
case UNDO_INSERT_4: case UNDO_BS_4: case UNDO_DEL_4:
@@ -1546,10 +1589,10 @@ void txt_print_undo(Text *text)
unsigned int uc;
char c[BLI_UTF8_MAX + 1];
size_t c_len;
- uc = text->undo_buf[i]; i++;
- uc = uc + (text->undo_buf[i] << 8); i++;
- uc = uc + (text->undo_buf[i] << 16); i++;
- uc = uc + (text->undo_buf[i] << 24); i++;
+ uc = utxt->buf[i]; i++;
+ uc = uc + (utxt->buf[i] << 8); i++;
+ uc = uc + (utxt->buf[i] << 16); i++;
+ uc = uc + (utxt->buf[i] << 24); i++;
c_len = BLI_str_utf8_from_unicode(uc, c);
c[c_len] = '\0';
puts(c);
@@ -1560,44 +1603,44 @@ void txt_print_undo(Text *text)
else if (op == UNDO_DBLOCK || op == UNDO_IBLOCK) {
i++;
- linep = text->undo_buf[i]; i++;
- linep = linep + (text->undo_buf[i] << 8); i++;
- linep = linep + (text->undo_buf[i] << 16); i++;
- linep = linep + (text->undo_buf[i] << 24); i++;
+ linep = utxt->buf[i]; i++;
+ linep = linep + (utxt->buf[i] << 8); i++;
+ linep = linep + (utxt->buf[i] << 16); i++;
+ linep = linep + (utxt->buf[i] << 24); i++;
printf(" (length %d) <", linep);
while (linep > 0) {
- putchar(text->undo_buf[i]);
+ putchar(utxt->buf[i]);
linep--; i++;
}
- linep = text->undo_buf[i]; i++;
- linep = linep + (text->undo_buf[i] << 8); i++;
- linep = linep + (text->undo_buf[i] << 16); i++;
- linep = linep + (text->undo_buf[i] << 24); i++;
+ linep = utxt->buf[i]; i++;
+ linep = linep + (utxt->buf[i] << 8); i++;
+ linep = linep + (utxt->buf[i] << 16); i++;
+ linep = linep + (utxt->buf[i] << 24); i++;
printf("> (%d)", linep);
}
else if (op == UNDO_INDENT || op == UNDO_UNINDENT) {
i++;
- charp = text->undo_buf[i]; i++;
- charp = charp + (text->undo_buf[i] << 8); i++;
+ charp = utxt->buf[i]; i++;
+ charp = charp + (utxt->buf[i] << 8); i++;
- linep = text->undo_buf[i]; i++;
- linep = linep + (text->undo_buf[i] << 8); i++;
- linep = linep + (text->undo_buf[i] << 16); i++;
- linep = linep + (text->undo_buf[i] << 24); i++;
+ linep = utxt->buf[i]; i++;
+ linep = linep + (utxt->buf[i] << 8); i++;
+ linep = linep + (utxt->buf[i] << 16); i++;
+ linep = linep + (utxt->buf[i] << 24); i++;
printf("to <%d, %d> ", linep, charp);
- charp = text->undo_buf[i]; i++;
- charp = charp + (text->undo_buf[i] << 8); i++;
+ charp = utxt->buf[i]; i++;
+ charp = charp + (utxt->buf[i] << 8); i++;
- linep = text->undo_buf[i]; i++;
- linep = linep + (text->undo_buf[i] << 8); i++;
- linep = linep + (text->undo_buf[i] << 16); i++;
- linep = linep + (text->undo_buf[i] << 24); i++;
+ linep = utxt->buf[i]; i++;
+ linep = linep + (utxt->buf[i] << 8); i++;
+ linep = linep + (utxt->buf[i] << 16); i++;
+ linep = linep + (utxt->buf[i] << 24); i++;
printf("from <%d, %d>", linep, charp);
}
@@ -1628,104 +1671,114 @@ static void txt_undo_store_uint32(char *undo_buf, int *undo_pos, unsigned int va
(*undo_pos)++;
}
-/* store the cur cursor to the undo buffer */
-static void txt_undo_store_cur(Text *text)
+/* store the cur cursor to the undo buffer (6 bytes)*/
+static void txt_undo_store_cur(Text *text, TextUndoBuf *utxt)
{
- txt_undo_store_uint16(text->undo_buf, &text->undo_pos, text->curc);
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, txt_get_span(text->lines.first, text->curl));
+ txt_undo_store_uint16(utxt->buf, &utxt->pos, text->curc);
+ txt_undo_store_uint32(utxt->buf, &utxt->pos, txt_get_span(text->lines.first, text->curl));
}
-/* store the sel cursor to the undo buffer */
-static void txt_undo_store_sel(Text *text)
+/* store the sel cursor to the undo buffer (6 bytes) */
+static void txt_undo_store_sel(Text *text, TextUndoBuf *utxt)
{
- txt_undo_store_uint16(text->undo_buf, &text->undo_pos, text->selc);
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, txt_get_span(text->lines.first, text->sell));
+ txt_undo_store_uint16(utxt->buf, &utxt->pos, text->selc);
+ txt_undo_store_uint32(utxt->buf, &utxt->pos, txt_get_span(text->lines.first, text->sell));
}
-/* store both cursors to the undo buffer */
-static void txt_undo_store_cursors(Text *text)
+/* store both cursors to the undo buffer (12 bytes) */
+static void txt_undo_store_cursors(Text *text, TextUndoBuf *utxt)
{
- txt_undo_store_cur(text);
- txt_undo_store_sel(text);
+ txt_undo_store_cur(text, utxt);
+ txt_undo_store_sel(text, utxt);
}
/* store an operator along with a block of data */
-static void txt_undo_add_blockop(Text *text, int op, const char *buf)
+static void txt_undo_add_blockop(Text *text, TextUndoBuf *utxt, int op, const char *buf)
{
unsigned int length = strlen(buf);
-
- if (!max_undo_test(text, length + 11 + 12))
- return;
-
- text->undo_pos++;
- text->undo_buf[text->undo_pos] = op;
- text->undo_pos++;
-
- txt_undo_store_cursors(text);
-
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length);
-
- strncpy(text->undo_buf + text->undo_pos, buf, length);
- text->undo_pos += length;
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length);
- text->undo_buf[text->undo_pos] = op;
-
- text->undo_buf[text->undo_pos + 1] = 0;
+ if (!max_undo_test(utxt, 2 + 12 + 4 + length + 4 + 1)) {
+ return;
+ }
+ /* 2 bytes */
+ utxt->pos++;
+ utxt->buf[utxt->pos] = op;
+ utxt->pos++;
+ /* 12 bytes */
+ txt_undo_store_cursors(text, utxt);
+ /* 4 bytes */
+ txt_undo_store_uint32(utxt->buf, &utxt->pos, length);
+ /* 'length' bytes */
+ strncpy(utxt->buf + utxt->pos, buf, length);
+ utxt->pos += length;
+ /* 4 bytes */
+ txt_undo_store_uint32(utxt->buf, &utxt->pos, length);
+ /* 1 byte */
+ utxt->buf[utxt->pos] = op;
+
+ txt_undo_end(text, utxt);
}
/* store a regular operator */
-void txt_undo_add_op(Text *text, int op)
+void txt_undo_add_op(Text *text, TextUndoBuf *utxt, int op)
{
- if (!max_undo_test(text, 15))
+ if (!max_undo_test(utxt, 2 + 12 + 1)) {
return;
+ }
- text->undo_pos++;
- text->undo_buf[text->undo_pos] = op;
+ /* 2 bytes */
+ utxt->pos++;
+ utxt->buf[utxt->pos] = op;
+ utxt->pos++;
+ /* 12 bytes */
+ txt_undo_store_cursors(text, utxt);
+ /* 1 byte */
+ utxt->buf[utxt->pos] = op;
- text->undo_pos++;
-
- txt_undo_store_cursors(text);
-
- text->undo_buf[text->undo_pos] = op;
- text->undo_buf[text->undo_pos + 1] = 0;
+ txt_undo_end(text, utxt);
}
/* store an operator for a single character */
-static void txt_undo_add_charop(Text *text, int op_start, unsigned int c)
+static void txt_undo_add_charop(Text *text, TextUndoBuf *utxt, int op_start, unsigned int c)
{
char utf8[BLI_UTF8_MAX];
size_t i, utf8_size = BLI_str_utf8_from_unicode(c, utf8);
- if (!max_undo_test(text, 3 + utf8_size + 12))
- return;
-
- text->undo_pos++;
-
- if (utf8_size < 4) {
- text->undo_buf[text->undo_pos] = op_start + utf8_size - 1;
- text->undo_pos++;
-
- txt_undo_store_cur(text);
-
+ if (utf8_size < 4 && 0) {
+ if (!max_undo_test(utxt, 2 + 6 + utf8_size + 1)) {
+ return;
+ }
+ /* 2 bytes */
+ utxt->pos++;
+ utxt->buf[utxt->pos] = op_start + utf8_size - 1;
+ utxt->pos++;
+ /* 6 bytes */
+ txt_undo_store_cur(text, utxt);
+ /* 'utf8_size' bytes */
for (i = 0; i < utf8_size; i++) {
- text->undo_buf[text->undo_pos] = utf8[i];
- text->undo_pos++;
+ utxt->buf[utxt->pos] = utf8[i];
+ utxt->pos++;
}
-
- text->undo_buf[text->undo_pos] = op_start + utf8_size - 1;
+ /* 1 byte */
+ utxt->buf[utxt->pos] = op_start + utf8_size - 1;
}
else {
- text->undo_buf[text->undo_pos] = op_start + 3;
- text->undo_pos++;
-
- txt_undo_store_cursors(text);
-
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, c);
- text->undo_buf[text->undo_pos] = op_start + 3;
+ if (!max_undo_test(utxt, 2 + 6 + 4 + 1)) {
+ return;
+ }
+ /* 2 bytes */
+ utxt->pos++;
+ utxt->buf[utxt->pos] = op_start + 3;
+ utxt->pos++;
+ /* 6 bytes */
+ txt_undo_store_cur(text, utxt);
+ /* 4 bytes */
+ txt_undo_store_uint32(utxt->buf, &utxt->pos, c);
+ /* 1 byte */
+ utxt->buf[utxt->pos] = op_start + 3;
}
- text->undo_buf[text->undo_pos + 1] = 0;
+ txt_undo_end(text, utxt);
}
/* extends Link */
@@ -1739,7 +1792,7 @@ struct LinkInt {
* of the lines that should not be indented back.
*/
static void txt_undo_add_unprefix_op(
- Text *text, char undo_op,
+ Text *text, TextUndoBuf *utxt, char undo_op,
const ListBase *line_index_mask, const int line_index_mask_len)
{
struct LinkInt *idata;
@@ -1747,30 +1800,35 @@ static void txt_undo_add_unprefix_op(
BLI_assert(BLI_listbase_count(line_index_mask) == line_index_mask_len);
/* OP byte + UInt32 count + counted UInt32 line numbers + UInt32 count + 12-bytes selection + OP byte */
- if (!max_undo_test(text, 1 + 4 + (line_index_mask_len * 4) + 4 + 12 + 1)) {
+ if (!max_undo_test(utxt, 2 + 4 + (line_index_mask_len * 4) + 4 + 12 + 1)) {
return;
}
- /* Opening buffer sequence with OP */
- text->undo_pos++;
- text->undo_buf[text->undo_pos] = undo_op;
- text->undo_pos++;
- /* Adding number of line numbers to read */
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len);
+ /* 2 bytes */
+ utxt->pos++;
+ utxt->buf[utxt->pos] = undo_op;
+ utxt->pos++;
+ /* Adding number of line numbers to read
+ * 4 bytes */
+ txt_undo_store_uint32(utxt->buf, &utxt->pos, line_index_mask_len);
- /* Adding linenumbers of lines that shall not be indented if undoing */
+ /* Adding linenumbers of lines that shall not be indented if undoing.
+ * 'line_index_mask_len * 4' bytes */
for (idata = line_index_mask->first; idata; idata = idata->next) {
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, idata->value);
- }
-
- /* Adding number of line numbers to read again */
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len);
- /* Adding current selection */
- txt_undo_store_cursors(text);
- /* Closing with OP (same as above) */
- text->undo_buf[text->undo_pos] = undo_op;
+ txt_undo_store_uint32(utxt->buf, &utxt->pos, idata->value);
+ }
+
+ /* Adding number of line numbers to read again.
+ * 4 bytes */
+ txt_undo_store_uint32(utxt->buf, &utxt->pos, line_index_mask_len);
+ /* Adding current selection.
+ * 12 bytes */
+ txt_undo_store_cursors(text, utxt);
+ /* Closing with OP (same as above).
+ * 1 byte */
+ utxt->buf[utxt->pos] = undo_op;
/* Marking as last undo operation */
- text->undo_buf[text->undo_pos + 1] = 0;
+ txt_undo_end(text, utxt);
}
static unsigned short txt_undo_read_uint16(const char *undo_buf, int *undo_pos)
@@ -1913,7 +1971,7 @@ static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, s
unicode = BLI_str_utf8_as_unicode(utf8);
break;
case 4: /* 32-bit unicode symbol */
- unicode = txt_undo_read_uint32(undo_buf, undo_pos);
+ unicode = txt_redo_read_uint32(undo_buf, undo_pos);
break;
default:
/* should never happen */
@@ -1925,9 +1983,9 @@ static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, s
return unicode;
}
-void txt_do_undo(Text *text)
+void txt_do_undo(Text *text, TextUndoBuf *utxt)
{
- int op = text->undo_buf[text->undo_pos];
+ int op = utxt->buf[utxt->pos];
int prev_flags;
unsigned int linep;
unsigned int uni_char;
@@ -1936,11 +1994,11 @@ void txt_do_undo(Text *text)
unsigned short charp;
char *buf;
- if (text->undo_pos < 0) {
+ if (utxt->pos < 0) {
return;
}
- text->undo_pos--;
+ utxt->pos--;
undoing = 1;
@@ -1949,16 +2007,16 @@ void txt_do_undo(Text *text)
case UNDO_INSERT_2:
case UNDO_INSERT_3:
case UNDO_INSERT_4:
- text->undo_pos -= op - UNDO_INSERT_1 + 1;
+ utxt->pos -= op - UNDO_INSERT_1 + 1;
/* get and restore the cursors */
- txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
+ txt_undo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
- txt_delete_char(text);
+ txt_delete_char(text, utxt);
- text->undo_pos--;
+ utxt->pos--;
break;
case UNDO_BS_1:
@@ -1966,16 +2024,16 @@ void txt_do_undo(Text *text)
case UNDO_BS_3:
case UNDO_BS_4:
charp = op - UNDO_BS_1 + 1;
- uni_char = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp);
+ uni_char = txt_undo_read_unicode(utxt->buf, &utxt->pos, charp);
/* get and restore the cursors */
- txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
+ txt_undo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
- txt_add_char(text, uni_char);
+ txt_add_char(text, utxt, uni_char);
- text->undo_pos--;
+ utxt->pos--;
break;
case UNDO_DEL_1:
@@ -1983,50 +2041,50 @@ void txt_do_undo(Text *text)
case UNDO_DEL_3:
case UNDO_DEL_4:
charp = op - UNDO_DEL_1 + 1;
- uni_char = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp);
+ uni_char = txt_undo_read_unicode(utxt->buf, &utxt->pos, charp);
/* get and restore the cursors */
- txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
+ txt_undo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
- txt_add_char(text, uni_char);
+ txt_add_char(text, utxt, uni_char);
txt_move_left(text, 0);
- text->undo_pos--;
+ utxt->pos--;
break;
case UNDO_DBLOCK:
{
int i;
/* length of the string in the buffer */
- linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
+ linep = txt_undo_read_uint32(utxt->buf, &utxt->pos);
buf = MEM_mallocN(linep + 1, "dblock buffer");
for (i = 0; i < linep; i++) {
- buf[(linep - 1) - i] = text->undo_buf[text->undo_pos];
- text->undo_pos--;
+ buf[(linep - 1) - i] = utxt->buf[utxt->pos];
+ utxt->pos--;
}
buf[i] = 0;
/* skip over the length that was stored again */
- text->undo_pos -= 4;
+ utxt->pos -= 4;
/* Get the cursor positions */
- txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_undo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
/* move cur to location that needs buff inserted */
txt_move_to(text, curln, curc, 0);
- txt_insert_buf(text, buf);
+ txt_insert_buf(text, utxt, buf);
MEM_freeN(buf);
/* restore the cursors */
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
- text->undo_pos--;
+ utxt->pos--;
break;
}
@@ -2034,23 +2092,23 @@ void txt_do_undo(Text *text)
{
int i;
/* length of the string in the buffer */
- linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
+ linep = txt_undo_read_uint32(utxt->buf, &utxt->pos);
/* txt_backspace_char removes utf8-characters, not bytes */
buf = MEM_mallocN(linep + 1, "iblock buffer");
for (i = 0; i < linep; i++) {
- buf[(linep - 1) - i] = text->undo_buf[text->undo_pos];
- text->undo_pos--;
+ buf[(linep - 1) - i] = utxt->buf[utxt->pos];
+ utxt->pos--;
}
buf[i] = 0;
linep = BLI_strlen_utf8(buf);
MEM_freeN(buf);
/* skip over the length that was stored again */
- text->undo_pos -= 4;
+ utxt->pos -= 4;
/* get and restore the cursors */
- txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_undo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
@@ -2066,9 +2124,9 @@ void txt_do_undo(Text *text)
text->flags = prev_flags;
}
- txt_delete_selected(text);
+ txt_delete_selected(text, utxt);
- text->undo_pos--;
+ utxt->pos--;
break;
}
case UNDO_INDENT:
@@ -2077,37 +2135,37 @@ void txt_do_undo(Text *text)
case UNDO_MOVE_LINES_UP:
case UNDO_MOVE_LINES_DOWN:
/* get and restore the cursors */
- txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_undo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
if (op == UNDO_INDENT) {
- txt_unindent(text);
+ txt_unindent(text, utxt);
}
else if (op == UNDO_COMMENT) {
- txt_uncomment(text);
+ txt_uncomment(text, utxt);
}
else if (op == UNDO_DUPLICATE) {
txt_delete_line(text, text->curl->next);
}
else if (op == UNDO_MOVE_LINES_UP) {
- txt_move_lines(text, TXT_MOVE_LINE_DOWN);
+ txt_move_lines(text, utxt, TXT_MOVE_LINE_DOWN);
}
else if (op == UNDO_MOVE_LINES_DOWN) {
- txt_move_lines(text, TXT_MOVE_LINE_UP);
+ txt_move_lines(text, utxt, TXT_MOVE_LINE_UP);
}
- text->undo_pos--;
+ utxt->pos--;
break;
case UNDO_UNINDENT:
case UNDO_UNCOMMENT:
{
- void (*txt_prefix_fn)(Text *);
- void (*txt_unprefix_fn)(Text *);
+ void (*txt_prefix_fn)(Text *, TextUndoBuf *);
+ void (*txt_unprefix_fn)(Text *, TextUndoBuf *);
int count;
int i;
/* Get and restore the cursors */
- txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_undo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
@@ -2121,30 +2179,30 @@ void txt_do_undo(Text *text)
txt_unprefix_fn = txt_uncomment;
}
- txt_prefix_fn(text);
+ txt_prefix_fn(text, utxt);
/* Get the count */
- count = txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
+ count = txt_undo_read_uint32(utxt->buf, &utxt->pos);
/* Iterate! */
txt_pop_sel(text);
for (i = 0; i < count; i++) {
- txt_move_to(text, txt_undo_read_uint32(text->undo_buf, &text->undo_pos), 0, 0);
+ txt_move_to(text, txt_undo_read_uint32(utxt->buf, &utxt->pos), 0, 0);
/* Un-un-unindent/comment */
- txt_unprefix_fn(text);
+ txt_unprefix_fn(text, utxt);
}
/* Restore selection */
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
/* Jumo over count */
- txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
+ txt_undo_read_uint32(utxt->buf, &utxt->pos);
/* Jump over closing OP byte */
- text->undo_pos--;
+ utxt->pos--;
break;
}
default:
//XXX error("Undo buffer error - resetting");
- text->undo_pos = -1;
+ utxt->pos = -1;
break;
}
@@ -2152,7 +2210,7 @@ void txt_do_undo(Text *text)
undoing = 0;
}
-void txt_do_redo(Text *text)
+void txt_do_redo(Text *text, TextUndoBuf *utxt)
{
char op;
char *buf;
@@ -2162,11 +2220,11 @@ void txt_do_redo(Text *text)
unsigned int curln, selln;
unsigned short curc, selc;
- text->undo_pos++;
- op = text->undo_buf[text->undo_pos];
+ utxt->pos++;
+ op = utxt->buf[utxt->pos];
if (!op) {
- text->undo_pos--;
+ utxt->pos--;
return;
}
@@ -2177,35 +2235,35 @@ void txt_do_redo(Text *text)
case UNDO_INSERT_2:
case UNDO_INSERT_3:
case UNDO_INSERT_4:
- text->undo_pos++;
+ utxt->pos++;
/* get and restore the cursors */
- txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
+ txt_redo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
charp = op - UNDO_INSERT_1 + 1;
- uni_uchar = txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp);
+ uni_uchar = txt_redo_read_unicode(utxt->buf, &utxt->pos, charp);
- txt_add_char(text, uni_uchar);
+ txt_add_char(text, utxt, uni_uchar);
break;
case UNDO_BS_1:
case UNDO_BS_2:
case UNDO_BS_3:
case UNDO_BS_4:
- text->undo_pos++;
+ utxt->pos++;
/* get and restore the cursors */
- txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
+ txt_redo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
- text->undo_pos += op - UNDO_BS_1 + 1;
+ utxt->pos += op - UNDO_BS_1 + 1;
/* move right so we backspace the correct char */
txt_move_right(text, 0);
- txt_backspace_char(text);
+ txt_backspace_char(text, utxt);
break;
@@ -2213,60 +2271,60 @@ void txt_do_redo(Text *text)
case UNDO_DEL_2:
case UNDO_DEL_3:
case UNDO_DEL_4:
- text->undo_pos++;
+ utxt->pos++;
/* get and restore the cursors */
- txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
+ txt_redo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
- text->undo_pos += op - UNDO_DEL_1 + 1;
+ utxt->pos += op - UNDO_DEL_1 + 1;
- txt_delete_char(text);
+ txt_delete_char(text, utxt);
break;
case UNDO_DBLOCK:
- text->undo_pos++;
+ utxt->pos++;
/* get and restore the cursors */
- txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_redo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
/* length of the block */
- linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
+ linep = txt_redo_read_uint32(utxt->buf, &utxt->pos);
- text->undo_pos += linep;
+ utxt->pos += linep;
/* skip over the length that was stored again */
- text->undo_pos += 4;
+ utxt->pos += 4;
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
break;
case UNDO_IBLOCK:
- text->undo_pos++;
+ utxt->pos++;
/* get and restore the cursors */
- txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_redo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
/* length of the block */
- linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
+ linep = txt_redo_read_uint32(utxt->buf, &utxt->pos);
buf = MEM_mallocN(linep + 1, "iblock buffer");
- memcpy(buf, &text->undo_buf[text->undo_pos], linep);
- text->undo_pos += linep;
+ memcpy(buf, &utxt->buf[utxt->pos], linep);
+ utxt->pos += linep;
buf[linep] = 0;
- txt_insert_buf(text, buf);
+ txt_insert_buf(text, utxt, buf);
MEM_freeN(buf);
/* skip over the length that was stored again */
- text->undo_pos += 4;
+ utxt->pos += 4;
break;
@@ -2276,38 +2334,38 @@ void txt_do_redo(Text *text)
case UNDO_DUPLICATE:
case UNDO_MOVE_LINES_UP:
case UNDO_MOVE_LINES_DOWN:
- text->undo_pos++;
+ utxt->pos++;
/* get and restore the cursors */
- txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_redo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
if (op == UNDO_INDENT) {
- txt_indent(text);
+ txt_indent(text, utxt);
}
else if (op == UNDO_COMMENT) {
- txt_comment(text);
+ txt_comment(text, utxt);
}
else if (op == UNDO_UNCOMMENT) {
- txt_uncomment(text);
+ txt_uncomment(text, utxt);
}
else if (op == UNDO_DUPLICATE) {
- txt_duplicate_line(text);
+ txt_duplicate_line(text, utxt);
}
else if (op == UNDO_MOVE_LINES_UP) {
/* offset the cursor by + 1 */
txt_move_to(text, curln + 1, curc, 0);
txt_move_to(text, selln + 1, selc, 1);
- txt_move_lines(text, TXT_MOVE_LINE_UP);
+ txt_move_lines(text, utxt, TXT_MOVE_LINE_UP);
}
else if (op == UNDO_MOVE_LINES_DOWN) {
/* offset the cursor by - 1 */
txt_move_to(text, curln - 1, curc, 0);
txt_move_to(text, selln - 1, selc, 1);
- txt_move_lines(text, TXT_MOVE_LINE_DOWN);
+ txt_move_lines(text, utxt, TXT_MOVE_LINE_DOWN);
}
/* re-restore the cursors since they got moved when redoing */
@@ -2320,24 +2378,24 @@ void txt_do_redo(Text *text)
int count;
int i;
- text->undo_pos++;
+ utxt->pos++;
/* Scan all the stuff described in txt_undo_add_unindent_op */
- count = txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
+ count = txt_redo_read_uint32(utxt->buf, &utxt->pos);
for (i = 0; i < count; i++) {
- txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
+ txt_redo_read_uint32(utxt->buf, &utxt->pos);
}
/* Count again */
- txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
+ txt_redo_read_uint32(utxt->buf, &utxt->pos);
/* Get the selection and re-unindent */
- txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_redo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
- txt_unindent(text);
+ txt_unindent(text, utxt);
break;
}
default:
//XXX error("Undo buffer error - resetting");
- text->undo_pos = -1;
+ utxt->pos = -1;
break;
}
@@ -2349,16 +2407,16 @@ void txt_do_redo(Text *text)
/* Line editing functions */
/**************************/
-void txt_split_curline(Text *text)
+void txt_split_curline(Text *text, TextUndoBuf *utxt)
{
TextLine *ins;
char *left, *right;
if (!text->curl) return;
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
- if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, '\n');
+ if (!undoing) txt_undo_add_charop(text, utxt, UNDO_INSERT_1, '\n');
/* Make the two half strings */
@@ -2430,7 +2488,7 @@ static void txt_combine_lines(Text *text, TextLine *linea, TextLine *lineb)
txt_clean_text(text);
}
-void txt_duplicate_line(Text *text)
+void txt_duplicate_line(Text *text, TextUndoBuf *utxt)
{
TextLine *textline;
@@ -2443,18 +2501,18 @@ void txt_duplicate_line(Text *text)
txt_make_dirty(text);
txt_clean_text(text);
- if (!undoing) txt_undo_add_op(text, UNDO_DUPLICATE);
+ if (!undoing) txt_undo_add_op(text, utxt, UNDO_DUPLICATE);
}
}
-void txt_delete_char(Text *text)
+void txt_delete_char(Text *text, TextUndoBuf *utxt)
{
unsigned int c = '\n';
if (!text->curl) return;
if (txt_has_sel(text)) { /* deleting a selection */
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
txt_make_dirty(text);
return;
}
@@ -2480,24 +2538,24 @@ void txt_delete_char(Text *text)
txt_make_dirty(text);
txt_clean_text(text);
- if (!undoing) txt_undo_add_charop(text, UNDO_DEL_1, c);
+ if (!undoing) txt_undo_add_charop(text, utxt, UNDO_DEL_1, c);
}
-void txt_delete_word(Text *text)
+void txt_delete_word(Text *text, TextUndoBuf *utxt)
{
txt_jump_right(text, true, true);
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
txt_make_dirty(text);
}
-void txt_backspace_char(Text *text)
+void txt_backspace_char(Text *text, TextUndoBuf *utxt)
{
unsigned int c = '\n';
if (!text->curl) return;
if (txt_has_sel(text)) { /* deleting a selection */
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
txt_make_dirty(text);
return;
}
@@ -2529,13 +2587,13 @@ void txt_backspace_char(Text *text)
txt_make_dirty(text);
txt_clean_text(text);
- if (!undoing) txt_undo_add_charop(text, UNDO_BS_1, c);
+ if (!undoing) txt_undo_add_charop(text, utxt, UNDO_BS_1, c);
}
-void txt_backspace_word(Text *text)
+void txt_backspace_word(Text *text, TextUndoBuf *utxt)
{
txt_jump_left(text, true, true);
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
txt_make_dirty(text);
}
@@ -2544,17 +2602,17 @@ void txt_backspace_word(Text *text)
* Remember to change this string according to max tab size */
static char tab_to_spaces[] = " ";
-static void txt_convert_tab_to_spaces(Text *text)
+static void txt_convert_tab_to_spaces(Text *text, TextUndoBuf *utxt)
{
/* sb aims to pad adjust the tab-width needed so that the right number of spaces
* is added so that the indention of the line is the right width (i.e. aligned
* to multiples of TXT_TABSIZE)
*/
const char *sb = &tab_to_spaces[text->curc % TXT_TABSIZE];
- txt_insert_buf(text, sb);
+ txt_insert_buf(text, utxt, sb);
}
-static bool txt_add_char_intern(Text *text, unsigned int add, bool replace_tabs)
+static bool txt_add_char_intern(Text *text, TextUndoBuf *utxt, unsigned int add, bool replace_tabs)
{
char *tmp, ch[BLI_UTF8_MAX];
size_t add_len;
@@ -2562,19 +2620,19 @@ static bool txt_add_char_intern(Text *text, unsigned int add, bool replace_tabs)
if (!text->curl) return 0;
if (add == '\n') {
- txt_split_curline(text);
+ txt_split_curline(text, utxt);
return true;
}
/* insert spaces rather than tabs */
if (add == '\t' && replace_tabs) {
- txt_convert_tab_to_spaces(text);
+ txt_convert_tab_to_spaces(text, utxt);
return true;
}
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
- if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, add);
+ if (!undoing) txt_undo_add_charop(text, utxt, UNDO_INSERT_1, add);
add_len = BLI_str_utf8_from_unicode(add, ch);
@@ -2596,23 +2654,23 @@ static bool txt_add_char_intern(Text *text, unsigned int add, bool replace_tabs)
return 1;
}
-bool txt_add_char(Text *text, unsigned int add)
+bool txt_add_char(Text *text, TextUndoBuf *utxt, unsigned int add)
{
- return txt_add_char_intern(text, add, (text->flags & TXT_TABSTOSPACES) != 0);
+ return txt_add_char_intern(text, utxt, add, (text->flags & TXT_TABSTOSPACES) != 0);
}
-bool txt_add_raw_char(Text *text, unsigned int add)
+bool txt_add_raw_char(Text *text, TextUndoBuf *utxt, unsigned int add)
{
- return txt_add_char_intern(text, add, 0);
+ return txt_add_char_intern(text, utxt, add, 0);
}
-void txt_delete_selected(Text *text)
+void txt_delete_selected(Text *text, TextUndoBuf *utxt)
{
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
txt_make_dirty(text);
}
-bool txt_replace_char(Text *text, unsigned int add)
+bool txt_replace_char(Text *text, TextUndoBuf *utxt, unsigned int add)
{
unsigned int del;
size_t del_size = 0, add_size;
@@ -2622,7 +2680,7 @@ bool txt_replace_char(Text *text, unsigned int add)
/* If text is selected or we're at the end of the line just use txt_add_char */
if (text->curc == text->curl->len || txt_has_sel(text) || add == '\n') {
- return txt_add_char(text, add);
+ return txt_add_char(text, utxt, add);
}
del = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &del_size);
@@ -2650,10 +2708,10 @@ bool txt_replace_char(Text *text, unsigned int add)
/* Should probably create a new op for this */
if (!undoing) {
- txt_undo_add_charop(text, UNDO_INSERT_1, add);
+ txt_undo_add_charop(text, utxt, UNDO_INSERT_1, add);
text->curc -= add_size;
txt_pop_sel(text);
- txt_undo_add_charop(text, UNDO_DEL_1, del);
+ txt_undo_add_charop(text, utxt, UNDO_DEL_1, del);
text->curc += add_size;
txt_pop_sel(text);
}
@@ -2793,7 +2851,7 @@ static void txt_select_unprefix(
/* caller must handle undo */
}
-void txt_comment(Text *text)
+void txt_comment(Text *text, TextUndoBuf *utxt)
{
const char *prefix = "#";
@@ -2804,11 +2862,11 @@ void txt_comment(Text *text)
txt_select_prefix(text, prefix);
if (!undoing) {
- txt_undo_add_op(text, UNDO_COMMENT);
+ txt_undo_add_op(text, utxt, UNDO_COMMENT);
}
}
-void txt_uncomment(Text *text)
+void txt_uncomment(Text *text, TextUndoBuf *utxt)
{
const char *prefix = "#";
ListBase line_index_mask;
@@ -2821,13 +2879,13 @@ void txt_uncomment(Text *text)
txt_select_unprefix(text, prefix, &line_index_mask, &line_index_mask_len);
if (!undoing) {
- txt_undo_add_unprefix_op(text, UNDO_UNCOMMENT, &line_index_mask, line_index_mask_len);
+ txt_undo_add_unprefix_op(text, utxt, UNDO_UNCOMMENT, &line_index_mask, line_index_mask_len);
}
BLI_freelistN(&line_index_mask);
}
-void txt_indent(Text *text)
+void txt_indent(Text *text, TextUndoBuf *utxt)
{
const char *prefix = (text->flags & TXT_TABSTOSPACES) ? tab_to_spaces : "\t";
@@ -2838,11 +2896,11 @@ void txt_indent(Text *text)
txt_select_prefix(text, prefix);
if (!undoing) {
- txt_undo_add_op(text, UNDO_INDENT);
+ txt_undo_add_op(text, utxt, UNDO_INDENT);
}
}
-void txt_unindent(Text *text)
+void txt_unindent(Text *text, TextUndoBuf *utxt)
{
const char *prefix = (text->flags & TXT_TABSTOSPACES) ? tab_to_spaces : "\t";
ListBase line_index_mask;
@@ -2855,13 +2913,13 @@ void txt_unindent(Text *text)
txt_select_unprefix(text, prefix, &line_index_mask, &line_index_mask_len);
if (!undoing) {
- txt_undo_add_unprefix_op(text, UNDO_UNINDENT, &line_index_mask, line_index_mask_len);
+ txt_undo_add_unprefix_op(text, utxt, UNDO_UNINDENT, &line_index_mask, line_index_mask_len);
}
BLI_freelistN(&line_index_mask);
}
-void txt_move_lines(struct Text *text, const int direction)
+void txt_move_lines(struct Text *text, TextUndoBuf *utxt, const int direction)
{
TextLine *line_other;
@@ -2888,7 +2946,7 @@ void txt_move_lines(struct Text *text, const int direction)
txt_clean_text(text);
if (!undoing) {
- txt_undo_add_op(text, (direction == TXT_MOVE_LINE_DOWN) ? UNDO_MOVE_LINES_DOWN : UNDO_MOVE_LINES_UP);
+ txt_undo_add_op(text, utxt, (direction == TXT_MOVE_LINE_DOWN) ? UNDO_MOVE_LINES_DOWN : UNDO_MOVE_LINES_UP);
}
}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index fcedd880615..250408642bb 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -55,7 +55,6 @@
#include "IMB_imbuf.h"
-#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_colorband.h"
@@ -412,6 +411,7 @@ void BKE_texture_mtex_default(MTex *mtex)
mtex->kinkfac = 1.0f;
mtex->kinkampfac = 1.0f;
mtex->roughfac = 1.0f;
+ mtex->twistfac = 1.0f;
mtex->padensfac = 1.0f;
mtex->lifefac = 1.0f;
mtex->sizefac = 1.0f;
@@ -1206,17 +1206,17 @@ void BKE_texture_get_value(
BKE_texture_get_value_ex(scene, texture, tex_co, texres, NULL, use_color_management);
}
-static void texture_nodes_fetch_images_for_pool(bNodeTree *ntree, struct ImagePool *pool)
+static void texture_nodes_fetch_images_for_pool(Tex *texture, bNodeTree *ntree, struct ImagePool *pool)
{
for (bNode *node = ntree->nodes.first; node; node = node->next) {
if (node->type == SH_NODE_TEX_IMAGE && node->id != NULL) {
Image *image = (Image *)node->id;
- BKE_image_pool_acquire_ibuf(image, NULL, pool);
+ BKE_image_pool_acquire_ibuf(image, &texture->iuser, pool);
}
else if (node->type == NODE_GROUP && node->id != NULL) {
/* TODO(sergey): Do we need to control recursion here? */
bNodeTree *nested_tree = (bNodeTree *)node->id;
- texture_nodes_fetch_images_for_pool(nested_tree, pool);
+ texture_nodes_fetch_images_for_pool(texture, nested_tree, pool);
}
}
}
@@ -1225,12 +1225,12 @@ static void texture_nodes_fetch_images_for_pool(bNodeTree *ntree, struct ImagePo
void BKE_texture_fetch_images_for_pool(Tex *texture, struct ImagePool *pool)
{
if (texture->nodetree != NULL) {
- texture_nodes_fetch_images_for_pool(texture->nodetree, pool);
+ texture_nodes_fetch_images_for_pool(texture, texture->nodetree, pool);
}
else {
if (texture->type == TEX_IMAGE) {
if (texture->ima != NULL) {
- BKE_image_pool_acquire_ibuf(texture->ima, NULL, pool);
+ BKE_image_pool_acquire_ibuf(texture->ima, &texture->iuser, pool);
}
}
}
diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c
index dd7def16ca8..106dd125575 100644
--- a/source/blender/blenkernel/intern/tracking_region_tracker.c
+++ b/source/blender/blenkernel/intern/tracking_region_tracker.c
@@ -189,7 +189,7 @@ void tracking_configure_tracker(const MovieTrackingTrack *track, float *mask,
options->image1_mask = NULL;
}
-/* Peform tracking from a reference_marker to destination_ibuf.
+/* Perform tracking from a reference_marker to destination_ibuf.
* Uses marker as an initial position guess.
*
* Returns truth if tracker returned success, puts result
diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c
index d8e98291117..8c1b846db84 100644
--- a/source/blender/blenkernel/intern/tracking_util.c
+++ b/source/blender/blenkernel/intern/tracking_util.c
@@ -787,9 +787,9 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor,
* in the cache which is nice on the one hand (faster re-use of the
* frames) but on the other hand it bumps the memory usage up.
*/
- BLI_lock_thread(LOCK_MOVIECLIP);
+ BLI_thread_lock(LOCK_MOVIECLIP);
IMB_float_from_rect(orig_ibuf);
- BLI_unlock_thread(LOCK_MOVIECLIP);
+ BLI_thread_unlock(LOCK_MOVIECLIP);
final_ibuf = orig_ibuf;
}
/* Downscale if needed. */
diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c
new file mode 100644
index 00000000000..fd62650e898
--- /dev/null
+++ b/source/blender/blenkernel/intern/undo_system.c
@@ -0,0 +1,846 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/undo_system.c
+ * \ingroup bke
+ *
+ * Used by ED_undo.h, internal implementation.
+ */
+
+#include <string.h>
+
+#include "CLG_log.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_sys_types.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_sort_utils.h"
+
+#include "DNA_listBase.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_library_override.h"
+#include "BKE_main.h"
+#include "BKE_undo_system.h"
+
+#include "MEM_guardedalloc.h"
+
+#define undo_stack _wm_undo_stack_disallow /* pass in as a variable always. */
+
+/** Odd requirement of Blender that we always keep a memfile undo in the stack. */
+#define WITH_GLOBAL_UNDO_KEEP_ONE
+
+/** Make sure all ID's created at the point we add an undo step that uses ID's. */
+#define WITH_GLOBAL_UNDO_ENSURE_UPDATED
+
+/** We only need this locally. */
+static CLG_LogRef LOG = {"bke.undosys"};
+
+/* -------------------------------------------------------------------- */
+/** \name Internal Nested Undo Checks
+ *
+ * Make sure we're not running undo operations from 'step_encode', 'step_decode' callbacks.
+ * bugs caused by this situation aren't _that_ hard to spot but aren't always so obvious.
+ * Best we have a check which shows the problem immediately.
+ *
+ * \{ */
+#define WITH_NESTED_UNDO_CHECK
+
+#ifdef WITH_NESTED_UNDO_CHECK
+static bool g_undo_callback_running = false;
+# define UNDO_NESTED_ASSERT(state) BLI_assert(g_undo_callback_running == state)
+# define UNDO_NESTED_CHECK_BEGIN { \
+ UNDO_NESTED_ASSERT(false); \
+ g_undo_callback_running = true; \
+} ((void)0)
+# define UNDO_NESTED_CHECK_END { \
+ UNDO_NESTED_ASSERT(true); \
+ g_undo_callback_running = false; \
+} ((void)0)
+#else
+# define UNDO_NESTED_ASSERT(state) ((void)0)
+# define UNDO_NESTED_CHECK_BEGIN ((void)0)
+# define UNDO_NESTED_CHECK_END ((void)0)
+#endif
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Public Undo Types
+ *
+ * Unfortunately we need this for a handful of places.
+ */
+const UndoType *BKE_UNDOSYS_TYPE_IMAGE = NULL;
+const UndoType *BKE_UNDOSYS_TYPE_MEMFILE = NULL;
+const UndoType *BKE_UNDOSYS_TYPE_PAINTCURVE = NULL;
+const UndoType *BKE_UNDOSYS_TYPE_PARTICLE = NULL;
+const UndoType *BKE_UNDOSYS_TYPE_SCULPT = NULL;
+const UndoType *BKE_UNDOSYS_TYPE_TEXT = NULL;
+/** \} */
+
+/* UndoType */
+
+static ListBase g_undo_types = {NULL, NULL};
+
+static const UndoType *BKE_undosys_type_from_context(bContext *C)
+{
+ for (const UndoType *ut = g_undo_types.first; ut; ut = ut->next) {
+ /* No poll means we don't check context. */
+ if (ut->poll && ut->poll(C)) {
+ return ut;
+ }
+ }
+ return NULL;
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Internal Callback Wrappers
+ *
+ * #UndoRefID is simply a way to avoid inlining name copy and lookups,
+ * since it's easy to forget a single case when done inline (crashing in some cases).
+ *
+ * \{ */
+
+static void undosys_id_ref_store(void *UNUSED(user_data), UndoRefID *id_ref)
+{
+ BLI_assert(id_ref->name[0] == '\0');
+ if (id_ref->ptr) {
+ BLI_strncpy(id_ref->name, id_ref->ptr->name, sizeof(id_ref->name));
+ /* Not needed, just prevents stale data access. */
+ id_ref->ptr = NULL;
+ }
+}
+
+static void undosys_id_ref_resolve(void *user_data, UndoRefID *id_ref)
+{
+ /* Note: we could optimize this, for now it's not too bad since it only runs when we access undo! */
+ Main *bmain = user_data;
+ ListBase *lb = which_libbase(bmain, GS(id_ref->name));
+ for (ID *id = lb->first; id; id = id->next) {
+ if (STREQ(id_ref->name, id->name) && (id->lib == NULL)) {
+ id_ref->ptr = id;
+ break;
+ }
+ }
+}
+
+static bool undosys_step_encode(bContext *C, UndoStep *us)
+{
+ CLOG_INFO(&LOG, 2, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name);
+ UNDO_NESTED_CHECK_BEGIN;
+ bool ok = us->type->step_encode(C, us);
+ UNDO_NESTED_CHECK_END;
+ if (ok) {
+ if (us->type->step_foreach_ID_ref != NULL) {
+ /* Don't use from context yet because sometimes context is fake and not all members are filled in. */
+ Main *bmain = G.main;
+ us->type->step_foreach_ID_ref(us, undosys_id_ref_store, bmain);
+ }
+ }
+ if (ok == false) {
+ CLOG_INFO(&LOG, 2, "encode callback didn't create undo step");
+ }
+ return ok;
+}
+
+static void undosys_step_decode(bContext *C, UndoStep *us, int dir)
+{
+ CLOG_INFO(&LOG, 2, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name);
+ if (us->type->step_foreach_ID_ref) {
+ /* Don't use from context yet because sometimes context is fake and not all members are filled in. */
+ Main *bmain = G.main;
+ us->type->step_foreach_ID_ref(us, undosys_id_ref_resolve, bmain);
+ }
+
+ UNDO_NESTED_CHECK_BEGIN;
+ us->type->step_decode(C, us, dir);
+ UNDO_NESTED_CHECK_END;
+}
+
+static void undosys_step_free_and_unlink(UndoStack *ustack, UndoStep *us)
+{
+ CLOG_INFO(&LOG, 2, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name);
+ UNDO_NESTED_CHECK_BEGIN;
+ us->type->step_free(us);
+ UNDO_NESTED_CHECK_END;
+
+ BLI_remlink(&ustack->steps, us);
+ MEM_freeN(us);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Undo Stack
+ * \{ */
+
+#ifndef NDEBUG
+static void undosys_stack_validate(UndoStack *ustack, bool expect_non_empty)
+{
+ if (ustack->step_active != NULL) {
+ BLI_assert(!BLI_listbase_is_empty(&ustack->steps));
+ BLI_assert(BLI_findindex(&ustack->steps, ustack->step_active) != -1);
+ }
+ if (expect_non_empty) {
+ BLI_assert(!BLI_listbase_is_empty(&ustack->steps));
+ }
+}
+#else
+static void undosys_stack_validate(UndoStack *ustack, bool expect_non_empty)
+{
+ UNUSED_VARS(ustack, expect_non_empty);
+}
+#endif
+
+UndoStack *BKE_undosys_stack_create(void)
+{
+ UndoStack *ustack = MEM_callocN(sizeof(UndoStack), __func__);
+ return ustack;
+}
+
+void BKE_undosys_stack_destroy(UndoStack *ustack)
+{
+ BKE_undosys_stack_clear(ustack);
+ MEM_freeN(ustack);
+}
+
+void BKE_undosys_stack_clear(UndoStack *ustack)
+{
+ UNDO_NESTED_ASSERT(false);
+ CLOG_INFO(&LOG, 1, "steps=%d", BLI_listbase_count(&ustack->steps));
+ for (UndoStep *us = ustack->steps.last, *us_prev; us; us = us_prev) {
+ us_prev = us->prev;
+ undosys_step_free_and_unlink(ustack, us);
+ }
+ BLI_listbase_clear(&ustack->steps);
+ ustack->step_active = NULL;
+}
+
+static bool undosys_stack_push_main(UndoStack *ustack, const char *name, struct Main *bmain)
+{
+ UNDO_NESTED_ASSERT(false);
+ CLOG_INFO(&LOG, 1, "'%s'", name);
+ bContext *C_temp = CTX_create();
+ CTX_data_main_set(C_temp, bmain);
+ bool ok = BKE_undosys_step_push_with_type(ustack, C_temp, name, BKE_UNDOSYS_TYPE_MEMFILE);
+ CTX_free(C_temp);
+ return ok;
+}
+
+void BKE_undosys_stack_init_from_main(UndoStack *ustack, struct Main *bmain)
+{
+ UNDO_NESTED_ASSERT(false);
+ undosys_stack_push_main(ustack, "original", bmain);
+}
+
+/* name optional */
+bool BKE_undosys_stack_has_undo(UndoStack *ustack, const char *name)
+{
+ if (name) {
+ UndoStep *us = BLI_rfindstring(&ustack->steps, name, offsetof(UndoStep, name));
+ return us && us->prev;
+ }
+
+ return !BLI_listbase_is_empty(&ustack->steps);
+}
+
+UndoStep *BKE_undosys_stack_active_with_type(UndoStack *ustack, const UndoType *ut)
+{
+ UndoStep *us = ustack->step_active;
+ while (us && (us->type != ut)) {
+ us = us->prev;
+ }
+ return us;
+}
+
+UndoStep *BKE_undosys_stack_init_or_active_with_type(UndoStack *ustack, const UndoType *ut)
+{
+ UNDO_NESTED_ASSERT(false);
+ CLOG_INFO(&LOG, 1, "type='%s'", ut->name);
+ if (ustack->step_init && (ustack->step_init->type == ut)) {
+ return ustack->step_init;
+ }
+ return BKE_undosys_stack_active_with_type(ustack, ut);
+}
+
+/**
+ * \param steps: Limit the number of undo steps.
+ * \param memory_limit: Limit the amount of memory used by the undo stack.
+ */
+void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size_t memory_limit)
+{
+ UNDO_NESTED_ASSERT(false);
+ if (!(steps || memory_limit)) {
+ return;
+ }
+
+ CLOG_INFO(&LOG, 1, "steps=%d, memory_limit=%zu", steps, memory_limit);
+ UndoStep *us;
+#ifdef WITH_GLOBAL_UNDO_KEEP_ONE
+ UndoStep *us_exclude = NULL;
+#endif
+ /* keep at least two (original + other) */
+ size_t data_size_all = 0;
+ size_t us_count = 0;
+ for (us = ustack->steps.last; us && us->prev; us = us->prev) {
+ if (memory_limit) {
+ data_size_all += us->data_size;
+ if (data_size_all > memory_limit) {
+ break;
+ }
+ }
+ if (steps) {
+ if (us_count == steps) {
+ break;
+ }
+ if (us->skip == false) {
+ us_count += 1;
+ }
+ }
+ }
+
+ if (us) {
+ if (us->prev && us->prev->prev) {
+ us = us->prev;
+ }
+
+#ifdef WITH_GLOBAL_UNDO_KEEP_ONE
+ /* Hack, we need to keep at least one BKE_UNDOSYS_TYPE_MEMFILE. */
+ if (us->type != BKE_UNDOSYS_TYPE_MEMFILE) {
+ us_exclude = us->prev;
+ while (us_exclude && us->type != BKE_UNDOSYS_TYPE_MEMFILE) {
+ us_exclude = us_exclude->prev;
+ }
+ if (us_exclude) {
+ BLI_remlink(&ustack->steps, us_exclude);
+ }
+ }
+#endif
+ /* Free from first to last, free functions may update de-duplication info (see #MemFileUndoStep). */
+ while (ustack->steps.first != us) {
+ UndoStep *us_first = ustack->steps.first;
+ BLI_assert(us_first != ustack->step_active);
+ undosys_step_free_and_unlink(ustack, us_first);
+ }
+
+#ifdef WITH_GLOBAL_UNDO_KEEP_ONE
+ if (us_exclude) {
+ BLI_addhead(&ustack->steps, us_exclude);
+ }
+#endif
+ }
+}
+
+/** \} */
+
+UndoStep *BKE_undosys_step_push_init_with_type(UndoStack *ustack, bContext *C, const char *name, const UndoType *ut)
+{
+ UNDO_NESTED_ASSERT(false);
+ /* We could detect and clean this up (but it should never happen!). */
+ BLI_assert(ustack->step_init == NULL);
+ if (ut->step_encode_init) {
+ undosys_stack_validate(ustack, false);
+ UndoStep *us = MEM_callocN(ut->step_size, __func__);
+ CLOG_INFO(&LOG, 1, "addr=%p, name='%s', type='%s'", us, name, ut->name);
+ if (name != NULL) {
+ BLI_strncpy(us->name, name, sizeof(us->name));
+ }
+ us->type = ut;
+ ustack->step_init = us;
+ ut->step_encode_init(C, us);
+ undosys_stack_validate(ustack, true);
+ return us;
+ }
+ else {
+ return NULL;
+ }
+}
+
+UndoStep *BKE_undosys_step_push_init(UndoStack *ustack, bContext *C, const char *name)
+{
+ UNDO_NESTED_ASSERT(false);
+ /* We could detect and clean this up (but it should never happen!). */
+ BLI_assert(ustack->step_init == NULL);
+ const UndoType *ut = BKE_undosys_type_from_context(C);
+ if (ut == NULL) {
+ return NULL;
+ }
+ return BKE_undosys_step_push_init_with_type(ustack, C, name, ut);
+}
+
+bool BKE_undosys_step_push_with_type(UndoStack *ustack, bContext *C, const char *name, const UndoType *ut)
+{
+ UNDO_NESTED_ASSERT(false);
+ undosys_stack_validate(ustack, false);
+ bool is_not_empty = ustack->step_active != NULL;
+
+ /* Might not be final place for this to be called - probably only want to call it from some
+ * undo handlers, not all of them? */
+ BKE_main_override_static_operations_create(CTX_data_main(C));
+
+ /* Remove all undos after (also when 'ustack->step_active == NULL'). */
+ while (ustack->steps.last != ustack->step_active) {
+ UndoStep *us_iter = ustack->steps.last;
+ undosys_step_free_and_unlink(ustack, us_iter);
+ undosys_stack_validate(ustack, is_not_empty);
+ }
+
+ if (ustack->step_active) {
+ BLI_assert(BLI_findindex(&ustack->steps, ustack->step_active) != -1);
+ }
+
+#ifdef WITH_GLOBAL_UNDO_ENSURE_UPDATED
+ if (ut->step_foreach_ID_ref != NULL) {
+ Main *bmain = G.main;
+ if (bmain->is_memfile_undo_written == false) {
+ const char *name_internal = "MemFile Internal";
+ if (undosys_stack_push_main(ustack, name_internal, bmain)) {
+ UndoStep *us = ustack->steps.last;
+ BLI_assert(STREQ(us->name, name_internal));
+ us->skip = true;
+ }
+ }
+ }
+#endif
+
+ UndoStep *us = ustack->step_init ? ustack->step_init : MEM_callocN(ut->step_size, __func__);
+ ustack->step_init = NULL;
+ if (us->name[0] == '\0') {
+ BLI_strncpy(us->name, name, sizeof(us->name));
+ }
+ us->type = ut;
+ /* initialized, not added yet. */
+
+ if (undosys_step_encode(C, us)) {
+ ustack->step_active = us;
+ BLI_addtail(&ustack->steps, us);
+ undosys_stack_validate(ustack, true);
+ return true;
+ }
+ else {
+ MEM_freeN(us);
+ undosys_stack_validate(ustack, true);
+ return false;
+ }
+}
+
+bool BKE_undosys_step_push(UndoStack *ustack, bContext *C, const char *name)
+{
+ UNDO_NESTED_ASSERT(false);
+ const UndoType *ut = ustack->step_init ? ustack->step_init->type : BKE_undosys_type_from_context(C);
+ if (ut == NULL) {
+ return false;
+ }
+ return BKE_undosys_step_push_with_type(ustack, C, name, ut);
+}
+
+
+/**
+ * Useful when we want to diff against previous undo data but can't be sure the types match.
+ */
+UndoStep *BKE_undosys_step_same_type_next(UndoStep *us)
+{
+ if (us) {
+ const UndoType *ut = us->type;
+ while ((us = us->next)) {
+ if (us->type == ut) {
+ return us;
+ }
+ }
+
+ }
+ return us;
+}
+
+/**
+ * Useful when we want to diff against previous undo data but can't be sure the types match.
+ */
+UndoStep *BKE_undosys_step_same_type_prev(UndoStep *us)
+{
+ if (us) {
+ const UndoType *ut = us->type;
+ while ((us = us->prev)) {
+ if (us->type == ut) {
+ return us;
+ }
+ }
+
+ }
+ return us;
+}
+
+UndoStep *BKE_undosys_step_find_by_name_with_type(UndoStack *ustack, const char *name, const UndoType *ut)
+{
+ for (UndoStep *us = ustack->steps.last; us; us = us->prev) {
+ if (us->type == ut) {
+ if (STREQ(name, us->name)) {
+ return us;
+ }
+ }
+ }
+ return NULL;
+}
+
+UndoStep *BKE_undosys_step_find_by_name(UndoStack *ustack, const char *name)
+{
+ return BLI_rfindstring(&ustack->steps, name, offsetof(UndoStep, name));
+}
+
+UndoStep *BKE_undosys_step_find_by_type(UndoStack *ustack, const UndoType *ut)
+{
+ for (UndoStep *us = ustack->steps.last; us; us = us->prev) {
+ if (us->type == ut) {
+ return us;
+ }
+ }
+ return NULL;
+}
+
+bool BKE_undosys_step_undo_with_data_ex(
+ UndoStack *ustack, bContext *C, UndoStep *us,
+ bool use_skip)
+{
+ UNDO_NESTED_ASSERT(false);
+ if (us) {
+ undosys_stack_validate(ustack, true);
+ }
+ UndoStep *us_prev = us ? us->prev : NULL;
+ if (us && us->type->mode == BKE_UNDOTYPE_MODE_STORE) {
+ /* The current state is a copy, we need to load the previous state. */
+ us = us_prev;
+ }
+
+ if (us != NULL) {
+ CLOG_INFO(&LOG, 1, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name);
+ undosys_step_decode(C, us, -1);
+ ustack->step_active = us_prev;
+ undosys_stack_validate(ustack, true);
+ if (use_skip) {
+ if (ustack->step_active && ustack->step_active->skip) {
+ CLOG_INFO(&LOG, 2, "undo continue with skip %p '%s', type='%s'", us, us->name, us->type->name);
+ BKE_undosys_step_undo_with_data(ustack, C, ustack->step_active);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+bool BKE_undosys_step_undo_with_data(UndoStack *ustack, bContext *C, UndoStep *us)
+{
+ return BKE_undosys_step_undo_with_data_ex(ustack, C, us, true);
+}
+
+bool BKE_undosys_step_undo(UndoStack *ustack, bContext *C)
+{
+ return BKE_undosys_step_undo_with_data(ustack, C, ustack->step_active);
+}
+
+void BKE_undosys_step_undo_from_index(UndoStack *ustack, bContext *C, int index)
+{
+ UndoStep *us = BLI_findlink(&ustack->steps, index);
+ BLI_assert(us->skip == false);
+ BKE_undosys_step_load_data(ustack, C, us);
+}
+
+bool BKE_undosys_step_redo_with_data_ex(
+ UndoStack *ustack, bContext *C, UndoStep *us,
+ bool use_skip)
+{
+ UNDO_NESTED_ASSERT(false);
+ UndoStep *us_next = us ? us->next : NULL;
+ /* Unlike undo accumulate, we always use the next. */
+ us = us_next;
+
+ if (us != NULL) {
+ CLOG_INFO(&LOG, 1, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name);
+ undosys_step_decode(C, us, 1);
+ ustack->step_active = us_next;
+ if (use_skip) {
+ if (ustack->step_active && ustack->step_active->skip) {
+ CLOG_INFO(&LOG, 2, "redo continue with skip %p '%s', type='%s'", us, us->name, us->type->name);
+ BKE_undosys_step_redo_with_data(ustack, C, ustack->step_active);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+bool BKE_undosys_step_redo_with_data(UndoStack *ustack, bContext *C, UndoStep *us)
+{
+ return BKE_undosys_step_redo_with_data_ex(ustack, C, us, true);
+}
+
+bool BKE_undosys_step_redo(UndoStack *ustack, bContext *C)
+{
+ return BKE_undosys_step_redo_with_data(ustack, C, ustack->step_active);
+}
+
+bool BKE_undosys_step_load_data(UndoStack *ustack, bContext *C, UndoStep *us)
+{
+ UNDO_NESTED_ASSERT(false);
+ const int index_active = BLI_findindex(&ustack->steps, ustack->step_active);
+ const int index_target = BLI_findindex(&ustack->steps, us);
+ BLI_assert(!ELEM(-1, index_active, index_target));
+ bool ok = true;
+
+ if (index_target < index_active) {
+ uint i = index_active - index_target;
+ while (i-- && ok) {
+ ok = BKE_undosys_step_undo_with_data_ex(ustack, C, ustack->step_active, false);
+ }
+ }
+ else if (index_target > index_active) {
+ uint i = index_target - index_active;
+ while (i-- && ok) {
+ ok = BKE_undosys_step_redo_with_data_ex(ustack, C, ustack->step_active, false);
+ }
+ }
+
+ if (ok) {
+ BLI_assert(ustack->step_active == us);
+ }
+
+ return ok;
+}
+
+bool BKE_undosys_step_undo_compat_only(UndoStack *ustack, bContext *C, int step)
+{
+ if (step == 0) {
+ return BKE_undosys_step_undo_with_data(ustack, C, ustack->step_active);
+ }
+ else if (step == 1) {
+ return BKE_undosys_step_undo(ustack, C);
+ }
+ else {
+ return BKE_undosys_step_redo(ustack, C);
+ }
+}
+/**
+ * Similar to #WM_operatortype_append
+ */
+UndoType *BKE_undosys_type_append(void (*undosys_fn)(UndoType *))
+{
+ UndoType *ut;
+
+ ut = MEM_callocN(sizeof(UndoType), __func__);
+
+ undosys_fn(ut);
+
+ BLI_assert(ut->mode != 0);
+
+ BLI_addtail(&g_undo_types, ut);
+
+ return ut;
+}
+
+void BKE_undosys_type_free_all(void)
+{
+ UndoType *ut;
+ while ((ut = BLI_pophead(&g_undo_types))) {
+ MEM_freeN(ut);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name ID Reference Utilities
+ *
+ * Unfortunately we need this for a handful of places.
+ */
+
+static void UNUSED_FUNCTION(BKE_undosys_foreach_ID_ref(
+ UndoStack *ustack, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data))
+{
+ for (UndoStep *us = ustack->steps.first; us; us = us->next) {
+ const UndoType *ut = us->type;
+ if (ut->step_foreach_ID_ref != NULL) {
+ ut->step_foreach_ID_ref(us, foreach_ID_ref_fn, user_data);
+ }
+ }
+}
+
+typedef struct UndoIDPtrMapItem {
+ /** Never changes (matches undo data). Use as sort key for binary search. */
+ const void *ptr;
+ /** Write the new pointers here. */
+ uint index;
+} UndoIDPtrMapItem;
+
+typedef struct UndoIDPtrMap {
+ UndoRefID *refs;
+ /**
+ * Pointer map, update 'dst' members before use.
+ * This is always sorted (adds some overhead when adding, in practice it's acceptable since).
+ */
+ UndoIDPtrMapItem *pmap;
+
+ /** Length for both 'refs' & 'pmap' */
+ uint len;
+ uint len_alloc;
+} UndoIDPtrMap;
+
+#ifdef DEBUG
+# define PMAP_DEFAULT_ALLOC 1
+#else
+# define PMAP_DEFAULT_ALLOC 32
+#endif
+
+void BKE_undosys_ID_map_foreach_ID_ref(
+ UndoIDPtrMap *map,
+ UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+{
+ for (uint i = 0; i < map->len; i++) {
+ foreach_ID_ref_fn(user_data, &map->refs[i]);
+ }
+}
+
+/**
+ * Return true when found, otherwise index is set to the index we should insert.
+ */
+static bool undosys_ID_map_lookup_index(const UndoIDPtrMap *map, const void *key, uint *r_index)
+{
+ const UndoIDPtrMapItem *pmap = map->pmap;
+ const uint len = map->len;
+ if (len == 0) {
+ if (*r_index) {
+ *r_index = 0;
+ }
+ return false;
+ }
+ int min = 0, max = len - 1;
+ while (min <= max) {
+ const uint mid = (min + max) / 2;
+ if (pmap[mid].ptr < key) {
+ min = mid + 1;
+ }
+ else if (pmap[mid].ptr == key) {
+ if (r_index) {
+ *r_index = mid;
+ }
+ return true;
+ }
+ else if (pmap[mid].ptr > key) {
+ max = mid - 1;
+ }
+ }
+ if (r_index) {
+ *r_index = min;
+ }
+ return false;
+}
+
+/**
+ * A set of ID's use for efficient decoding, so we can map pointers back to the newly loaded data
+ * without performing full look ups each time.
+ *
+ * This can be used as an old_pointer -> new_pointer lookup.
+ */
+UndoIDPtrMap *BKE_undosys_ID_map_create(void)
+{
+ UndoIDPtrMap *map = MEM_mallocN(sizeof(*map), __func__);
+ map->len_alloc = PMAP_DEFAULT_ALLOC;
+ map->refs = MEM_mallocN(sizeof(*map->refs) * map->len_alloc, __func__);
+ map->pmap = MEM_mallocN(sizeof(*map->pmap) * map->len_alloc, __func__);
+ map->len = 0;
+ return map;
+}
+void BKE_undosys_ID_map_destroy(UndoIDPtrMap *idpmap)
+{
+ MEM_SAFE_FREE(idpmap->refs);
+ MEM_SAFE_FREE(idpmap->pmap);
+ MEM_freeN(idpmap);
+}
+
+void BKE_undosys_ID_map_add(UndoIDPtrMap *map, ID *id)
+{
+ uint index;
+ if (id->lib != NULL) {
+ return;
+ }
+
+ if (undosys_ID_map_lookup_index(map, id, &index)) {
+ return; /* exists. */
+ }
+
+ const uint len_src = map->len;
+ const uint len_dst = map->len + 1;
+ if (len_dst > map->len_alloc) {
+ map->len_alloc *= 2;
+ BLI_assert(map->len_alloc >= len_dst);
+ map->pmap = MEM_reallocN(map->pmap, sizeof(*map->pmap) * map->len_alloc);
+ map->refs = MEM_reallocN(map->refs, sizeof(*map->refs) * map->len_alloc);
+ }
+
+#if 0 /* Will be done automatically in callback. */
+ BLI_strncpy(map->refs[len_src].name, id->name, sizeof(id->name));
+#else
+ map->refs[len_src].name[0] = '\0';
+#endif
+ map->refs[len_src].ptr = id;
+
+ if (len_src != 0 && index != len_src) {
+ memmove(&map->pmap[index + 1], &map->pmap[index], sizeof(*map->pmap) * (len_src - index));
+ }
+ map->pmap[index].ptr = id;
+ map->pmap[index].index = len_src;
+
+ map->len = len_dst;
+}
+
+ID *BKE_undosys_ID_map_lookup(const UndoIDPtrMap *map, const ID *id_src)
+{
+ /* We should only ever lookup indices which exist! */
+ uint index;
+ if (!undosys_ID_map_lookup_index(map, id_src, &index)) {
+ BLI_assert(0);
+ }
+ index = map->pmap[index].index;
+ ID *id_dst = map->refs[index].ptr;
+ BLI_assert(id_dst != NULL);
+ BLI_assert(STREQ(id_dst->name, map->refs[index].name));
+ return id_dst;
+}
+
+void BKE_undosys_ID_map_add_with_prev(UndoIDPtrMap *map, ID *id, ID **id_prev)
+{
+ if (id == *id_prev) {
+ return;
+ }
+ *id_prev = id;
+ BKE_undosys_ID_map_add(map, id);
+}
+
+ID *BKE_undosys_ID_map_lookup_with_prev(const UndoIDPtrMap *map, ID *id_src, ID *id_prev_match[2])
+{
+ if (id_src == id_prev_match[0]) {
+ return id_prev_match[1];
+ }
+ else {
+ ID *id_dst = BKE_undosys_ID_map_lookup(map, id_src);
+ id_prev_match[0] = id_src;
+ id_prev_match[1] = id_dst;
+ return id_dst;
+ }
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index 8554cf0fb28..afceea9dd5f 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -38,6 +38,7 @@
#include "BKE_main.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "BKE_object.h"
#include "BKE_workspace.h"
#include "DNA_object_types.h"
@@ -45,6 +46,8 @@
#include "DNA_screen_types.h"
#include "DNA_workspace_types.h"
+#include "DEG_depsgraph.h"
+
#include "MEM_guardedalloc.h"
@@ -166,6 +169,7 @@ void BKE_workspace_free(WorkSpace *workspace)
BKE_workspace_relations_free(&workspace->hook_layout_relations);
BKE_workspace_relations_free(&workspace->scene_viewlayer_relations);
+ BLI_freelistN(&workspace->owner_ids);
BLI_freelistN(&workspace->layouts);
BLI_freelistN(&workspace->transform_orientations);
@@ -353,22 +357,22 @@ WorkSpaceLayout *BKE_workspace_layout_iter_circular(
WorkSpaceLayout *iter_layout;
if (iter_backward) {
- BLI_LISTBASE_CIRCULAR_BACKWARD_BEGIN(&workspace->layouts, iter_layout, start)
+ LISTBASE_CIRCULAR_BACKWARD_BEGIN(&workspace->layouts, iter_layout, start)
{
if (!callback(iter_layout, arg)) {
return iter_layout;
}
}
- BLI_LISTBASE_CIRCULAR_BACKWARD_END(&workspace->layouts, iter_layout, start);
+ LISTBASE_CIRCULAR_BACKWARD_END(&workspace->layouts, iter_layout, start);
}
else {
- BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN(&workspace->layouts, iter_layout, start)
+ LISTBASE_CIRCULAR_FORWARD_BEGIN(&workspace->layouts, iter_layout, start)
{
if (!callback(iter_layout, arg)) {
return iter_layout;
}
}
- BLI_LISTBASE_CIRCULAR_FORWARD_END(&workspace->layouts, iter_layout, start)
+ LISTBASE_CIRCULAR_FORWARD_END(&workspace->layouts, iter_layout, start)
}
return NULL;
@@ -413,21 +417,6 @@ void BKE_workspace_active_screen_set(WorkSpaceInstanceHook *hook, WorkSpace *wor
BKE_workspace_hook_layout_for_workspace_set(hook, workspace, layout);
}
-#ifdef USE_WORKSPACE_MODE
-eObjectMode BKE_workspace_object_mode_get(const WorkSpace *workspace, const Scene *scene)
-{
- Base *active_base = BKE_workspace_active_base_get(workspace, scene);
- return active_base ? active_base->object->mode : OB_MODE_OBJECT;
-}
-void BKE_workspace_object_mode_set(WorkSpace *workspace, Scene *scene, const eObjectMode mode)
-{
- Base *active_base = BKE_workspace_active_base_get(workspace, scene);
- if (active_base) {
- active_base->object->mode = mode;
- }
-}
-#endif
-
Base *BKE_workspace_active_base_get(const WorkSpace *workspace, const Scene *scene)
{
ViewLayer *view_layer = BKE_workspace_view_layer_get(workspace, scene);
@@ -510,8 +499,7 @@ void BKE_workspace_use_scene_settings_set(WorkSpace *workspace, bool value)
/* Update / evaluate */
-void BKE_workspace_update_tagged(struct EvaluationContext *eval_ctx,
- Main *bmain,
+void BKE_workspace_update_tagged(Main *bmain,
WorkSpace *workspace,
Scene *scene)
{
@@ -519,5 +507,21 @@ void BKE_workspace_update_tagged(struct EvaluationContext *eval_ctx,
struct Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene,
view_layer,
true);
- BKE_scene_graph_update_tagged(eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
}
+
+
+bool BKE_workspace_owner_id_check(
+ const WorkSpace *workspace, const char *owner_id)
+{
+ if ((*owner_id == '\0') ||
+ ((workspace->flags & WORKSPACE_USE_FILTER_BY_ORIGIN) == 0))
+ {
+ return true;
+ }
+ else {
+ /* we could use hash lookup, for now this list is highly under < ~16 items. */
+ return BLI_findstring(&workspace->owner_ids, owner_id, offsetof(wmOwnerID, name)) != NULL;
+ }
+}
+
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 5da8dc563e2..e87e84736c8 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -33,6 +33,7 @@
#include <string.h>
#include <stdlib.h>
#include <math.h>
+
#include "MEM_guardedalloc.h"
#include "DNA_world_types.h"
@@ -196,7 +197,7 @@ void BKE_world_make_local(Main *bmain, World *wrld, const bool lib_local)
void BKE_world_eval(const struct EvaluationContext *UNUSED(eval_ctx), World *world)
{
- if (G.debug & G_DEBUG_DEPSGRAPH) {
+ if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) {
printf("%s on %s (%p)\n", __func__, world->id.name, world);
}
if (!BLI_listbase_is_empty(&world->gpumaterial)) {
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index f745a840cea..0a2527bafd2 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -53,6 +53,7 @@
#include "BKE_global.h"
#include "BKE_idprop.h"
+#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_sound.h"
@@ -62,6 +63,8 @@
#include "ffmpeg_compat.h"
+struct StampData;
+
typedef struct FFMpegContext {
int ffmpeg_type;
int ffmpeg_codec;
@@ -94,6 +97,8 @@ typedef struct FFMpegContext {
bool audio_deinterleave;
int audio_sample_size;
+ struct StampData *stamp_data;
+
#ifdef WITH_AUDASPACE
AUD_Device *audio_mixdown_device;
#endif
@@ -577,24 +582,33 @@ static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int
}
if (context->ffmpeg_preset) {
- char const *preset_name;
+ /* 'preset' is used by h.264, 'deadline' is used by webm/vp9. I'm not
+ * setting those properties conditionally based on the video codec,
+ * as the FFmpeg encoder simply ignores unknown settings anyway. */
+ char const *preset_name = NULL; /* used by h.264 */
+ char const *deadline_name = NULL; /* used by webm/vp9 */
switch (context->ffmpeg_preset) {
- case FFM_PRESET_ULTRAFAST: preset_name = "ultrafast"; break;
- case FFM_PRESET_SUPERFAST: preset_name = "superfast"; break;
- case FFM_PRESET_VERYFAST: preset_name = "veryfast"; break;
- case FFM_PRESET_FASTER: preset_name = "faster"; break;
- case FFM_PRESET_FAST: preset_name = "fast"; break;
- case FFM_PRESET_MEDIUM: preset_name = "medium"; break;
- case FFM_PRESET_SLOW: preset_name = "slow"; break;
- case FFM_PRESET_SLOWER: preset_name = "slower"; break;
- case FFM_PRESET_VERYSLOW: preset_name = "veryslow"; break;
+ case FFM_PRESET_GOOD:
+ preset_name = "medium";
+ deadline_name = "good";
+ break;
+ case FFM_PRESET_BEST:
+ preset_name = "slower";
+ deadline_name = "best";
+ break;
+ case FFM_PRESET_REALTIME:
+ preset_name = "superfast";
+ deadline_name = "realtime";
+ break;
default:
printf("Unknown preset number %i, ignoring.\n", context->ffmpeg_preset);
- preset_name = NULL;
}
if (preset_name != NULL) {
av_dict_set(&opts, "preset", preset_name, 0);
}
+ if (deadline_name != NULL) {
+ av_dict_set(&opts, "deadline", deadline_name, 0);
+ }
}
#if 0
@@ -836,6 +850,12 @@ static void ffmpeg_dict_set_float(AVDictionary **dict, const char *key, float va
av_dict_set(dict, key, buffer, 0);
}
+static void ffmpeg_add_metadata_callback(void *data, const char *propname, char *propvalue, int len)
+{
+ AVDictionary **metadata = (AVDictionary **)data;
+ av_dict_set(metadata, propname, propvalue, 0);
+}
+
static int start_ffmpeg_impl(FFMpegContext *context, struct RenderData *rd, int rectx, int recty, const char *suffix, ReportList *reports)
{
/* Handle to the output file */
@@ -994,6 +1014,11 @@ static int start_ffmpeg_impl(FFMpegContext *context, struct RenderData *rd, int
goto fail;
}
}
+
+ if (context->stamp_data != NULL) {
+ BKE_stamp_info_callback(&of->metadata, context->stamp_data, ffmpeg_add_metadata_callback, false);
+ }
+
if (avformat_write_header(of, NULL) < 0) {
BKE_report(reports, RPT_ERROR, "Could not initialize streams, probably unsupported codec combination");
goto fail;
@@ -1168,6 +1193,7 @@ int BKE_ffmpeg_start(void *context_v, struct Scene *scene, RenderData *rd, int r
context->ffmpeg_autosplit_count = 0;
context->ffmpeg_preview = preview;
+ context->stamp_data = BKE_stamp_info_from_scene_static(scene);
success = start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports);
#ifdef WITH_AUDASPACE
@@ -1659,7 +1685,7 @@ void BKE_ffmpeg_image_type_verify(RenderData *rd, ImageFormatData *imf)
{
BKE_ffmpeg_preset_set(rd, FFMPEG_PRESET_H264);
rd->ffcodecdata.constant_rate_factor = FFM_CRF_MEDIUM;
- rd->ffcodecdata.ffmpeg_preset = FFM_PRESET_MEDIUM;
+ rd->ffcodecdata.ffmpeg_preset = FFM_PRESET_GOOD;
rd->ffcodecdata.type = FFMPEG_MKV;
}
if (rd->ffcodecdata.type == FFMPEG_OGG) {
@@ -1734,6 +1760,7 @@ void *BKE_ffmpeg_context_create(void)
context->ffmpeg_autosplit = 0;
context->ffmpeg_autosplit_count = 0;
context->ffmpeg_preview = false;
+ context->stamp_data = NULL;
return context;
}
@@ -1741,9 +1768,13 @@ void *BKE_ffmpeg_context_create(void)
void BKE_ffmpeg_context_free(void *context_v)
{
FFMpegContext *context = context_v;
- if (context) {
- MEM_freeN(context);
+ if (context == NULL) {
+ return;
+ }
+ if (context->stamp_data) {
+ MEM_freeN(context->stamp_data);
}
+ MEM_freeN(context);
}
#endif /* WITH_FFMPEG */
diff --git a/source/blender/blenkernel/particle_private.h b/source/blender/blenkernel/particle_private.h
new file mode 100644
index 00000000000..2189527118b
--- /dev/null
+++ b/source/blender/blenkernel/particle_private.h
@@ -0,0 +1,54 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2018 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/particle_private.h
+ * \ingroup bke
+ */
+
+#ifndef __PARTICLE_PRIVATE_H__
+#define __PARTICLE_PRIVATE_H__
+
+typedef struct ParticleChildModifierContext {
+ ParticleThreadContext *thread_ctx;
+ ParticleSimulationData *sim;
+ ParticleTexture *ptex;
+ ChildParticle *cpa;
+ const float *par_co; /* float3 */
+ const float *par_vel; /* float3 */
+ const float *par_rot; /* float4 */
+ const float *par_orco; /* float3 */
+ const float *orco; /* float3 */
+ ParticleCacheKey *parent_keys;
+} ParticleChildModifierContext;
+
+void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape, float amplitude, float flat,
+ short type, short axis, float obmat[4][4], int smooth_start);
+float do_clump(ParticleKey *state, const float par_co[3], float time, const float orco_offset[3], float clumpfac, float clumppow, float pa_clump,
+ bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve);
+void do_child_modifiers(const ParticleChildModifierContext *modifier_ctx,
+ float mat[4][4], ParticleKey *state, float t);
+
+#endif /* __PARTICLE_PRIVATE_H__ */
diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h
index 3ffca818c0d..8e94b8197ef 100644
--- a/source/blender/blenlib/BLI_array.h
+++ b/source/blender/blenlib/BLI_array.h
@@ -62,9 +62,10 @@
* Doing the realloc in a macro isn't so simple,
* so use a function the macros can use.
*/
-void _bli_array_grow_func(void **arr_p, const void *arr_static,
- const int sizeof_arr_p, const int arr_count, const int num,
- const char *alloc_str);
+void _bli_array_grow_func(
+ void **arr_p, const void *arr_static,
+ const int sizeof_arr_p, const int arr_len, const int num,
+ const char *alloc_str);
/* -------------------------------------------------------------------- */
@@ -74,18 +75,18 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
/** use ``sizeof(*(arr))`` to ensure the array exists and is an array */
#define BLI_array_declare(arr) \
- int _##arr##_count = ((void)(sizeof(*(arr))), 0); \
+ int _##arr##_len = ((void)(sizeof(*(arr))), 0); \
void *_##arr##_static = NULL
/**
* this will use stack space, up to maxstatic array elements, before
* switching to dynamic heap allocation */
#define BLI_array_staticdeclare(arr, maxstatic) \
- int _##arr##_count = 0; \
+ int _##arr##_len = 0; \
char _##arr##_static[maxstatic * sizeof(*(arr))]
/** returns the logical size of the array, not including buffering. */
-#define BLI_array_count(arr) ((void)0, _##arr##_count)
+#define BLI_array_len(arr) ((void)0, _##arr##_len)
/**
* Grow the array by a fixed number of items.
@@ -95,23 +96,23 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
#define BLI_array_reserve(arr, num) (void)( \
(((void *)(arr) == NULL) && \
((void *)(_##arr##_static) != NULL) && \
- /* don't add _##arr##_count below because it must be zero */ \
- (_bli_array_totalsize_static(arr) >= _##arr##_count + (num))) ? \
+ /* 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 */ \
(void)(arr = (void *)_##arr##_static) \
: \
/* use existing static array or allocate */ \
- (LIKELY(_bli_array_totalsize(arr) >= _##arr##_count + (num)) ? \
+ (LIKELY(_bli_array_totalsize(arr) >= _##arr##_len + (num)) ? \
(void)0 /* do nothing */ : \
_bli_array_grow_func((void **)&(arr), _##arr##_static, \
- sizeof(*(arr)), _##arr##_count, num, \
+ sizeof(*(arr)), _##arr##_len, num, \
"BLI_array." #arr)) \
)
/** returns length of array */
#define BLI_array_grow_items(arr, num) \
- (BLI_array_reserve(arr, num), (_##arr##_count += num))
+ (BLI_array_reserve(arr, num), (_##arr##_len += num))
#define BLI_array_grow_one(arr) \
BLI_array_grow_items(arr, 1)
@@ -119,7 +120,7 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
/** appends an item to the array. */
#define BLI_array_append(arr, item) ( \
(void) BLI_array_grow_one(arr), \
- (void) (arr[_##arr##_count - 1] = item) \
+ (void) (arr[_##arr##_len - 1] = item) \
)
/**
@@ -127,13 +128,13 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
* item is not a pointer, but actual data value.*/
#define BLI_array_append_r(arr, item) ( \
(void) BLI_array_grow_one(arr), \
- (void) (arr[_##arr##_count - 1] = item), \
- (&arr[_##arr##_count - 1]) \
+ (void) (arr[_##arr##_len - 1] = item), \
+ (&arr[_##arr##_len - 1]) \
)
/** appends (grows) & returns a pointer to the uninitialized memory */
#define BLI_array_append_ret(arr) \
- (BLI_array_reserve(arr, 1), &arr[(_##arr##_count++)])
+ (BLI_array_reserve(arr, 1), &arr[(_##arr##_len++)])
#define BLI_array_free(arr) { \
if (arr && (char *)arr != _##arr##_static) { \
@@ -143,26 +144,26 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
} ((void)0)
#define BLI_array_pop(arr) ( \
- (arr && _##arr##_count) ? \
- arr[--_##arr##_count] : \
+ (arr && _##arr##_len) ? \
+ arr[--_##arr##_len] : \
NULL \
)
/**
- * resets the logical size of an array to zero, but doesn't
+ * Resets the logical size of an array to zero, but doesn't
* free the memory. */
-#define BLI_array_empty(arr) \
- { _##arr##_count = 0; } (void)0
+#define BLI_array_clear(arr) \
+ { _##arr##_len = 0; } ((void)0)
/**
- * set the count of the array, doesn't actually increase the allocated array
+ * Set the length of the array, doesn't actually increase the allocated array
* size. don't use this unless you know what you're doing. */
-#define BLI_array_count_set(arr, count) \
- { _##arr##_count = (count); }(void)0
+#define BLI_array_len_set(arr, len) \
+ { _##arr##_len = (len); } ((void)0)
/** only to prevent unused warnings */
#define BLI_array_fake_user(arr) \
- ((void)_##arr##_count, \
+ ((void)_##arr##_len, \
(void)_##arr##_static)
/** \} */
@@ -191,7 +192,7 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
#define BLI_array_fixedstack_free(arr) \
if (_##arr##_is_static) { \
MEM_freeN(arr); \
- } (void)0
+ } ((void)0)
/** \} */
diff --git a/source/blender/blenlib/BLI_array_utils.h b/source/blender/blenlib/BLI_array_utils.h
index a46c87cec40..9a510bcfc3b 100644
--- a/source/blender/blenlib/BLI_array_utils.h
+++ b/source/blender/blenlib/BLI_array_utils.h
@@ -74,10 +74,18 @@ bool _bli_array_iter_span(
bool use_wrap, bool use_delimit_bounds,
bool (*test_fn)(const void *arr_item, void *user_data), void *user_data,
unsigned int span_step[2], unsigned int *r_span_len);
-#define BLI_array_iter_span(arr, arr_len, use_wrap, use_delimit_bounds, test_fn, user_data, \
- span_step, r_span_len) \
+#define BLI_array_iter_span( \
+ arr, arr_len, use_wrap, use_delimit_bounds, test_fn, user_data, \
+ span_step, r_span_len) \
_bli_array_iter_span( \
arr, arr_len, sizeof(*(arr)), use_wrap, use_delimit_bounds, test_fn, user_data, \
span_step, r_span_len)
+bool _bli_array_is_zeroed(
+ const void *arr,
+ unsigned int arr_len, size_t arr_stride);
+#define BLI_array_is_zeroed(arr, arr_len) \
+ _bli_array_is_zeroed( \
+ arr, arr_len, sizeof(*(arr)))
+
#endif /* __BLI_ARRAY_UTILS_H__ */
diff --git a/source/blender/blenlib/BLI_assert.h b/source/blender/blenlib/BLI_assert.h
new file mode 100644
index 00000000000..b66b95b21fe
--- /dev/null
+++ b/source/blender/blenlib/BLI_assert.h
@@ -0,0 +1,106 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_ASSERT_H__
+#define __BLI_ASSERT_H__
+
+/** \file BLI_assert.h
+ * \ingroup bli
+ *
+ * Defines:
+ * - #BLI_assert
+ * - #BLI_STATIC_ASSERT
+ * - #BLI_STATIC_ASSERT_ALIGN
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef NDEBUG /* for BLI_assert */
+#include <stdio.h>
+#endif
+
+/* BLI_assert(), default only to print
+ * for aborting need to define WITH_ASSERT_ABORT
+ */
+/* For 'abort' only. */
+#include <stdlib.h>
+
+#ifndef NDEBUG
+# include "BLI_system.h"
+ /* _BLI_ASSERT_PRINT_POS */
+# if defined(__GNUC__)
+# define _BLI_ASSERT_PRINT_POS(a) \
+ fprintf(stderr, "BLI_assert failed: %s:%d, %s(), at \'%s\'\n", __FILE__, __LINE__, __func__, #a)
+# elif defined(_MSC_VER)
+# define _BLI_ASSERT_PRINT_POS(a) \
+ fprintf(stderr, "BLI_assert failed: %s:%d, %s(), at \'%s\'\n", __FILE__, __LINE__, __FUNCTION__, #a)
+# else
+# define _BLI_ASSERT_PRINT_POS(a) \
+ fprintf(stderr, "BLI_assert failed: %s:%d, at \'%s\'\n", __FILE__, __LINE__, #a)
+# endif
+ /* _BLI_ASSERT_ABORT */
+# ifdef WITH_ASSERT_ABORT
+# define _BLI_ASSERT_ABORT abort
+# else
+# define _BLI_ASSERT_ABORT() (void)0
+# endif
+ /* BLI_assert */
+# define BLI_assert(a) \
+ (void)((!(a)) ? ((BLI_system_backtrace(stderr), _BLI_ASSERT_PRINT_POS(a), _BLI_ASSERT_ABORT(), NULL)) : NULL)
+#else
+# define BLI_assert(a) ((void)0)
+#endif
+
+/* C++ can't use _Static_assert, expects static_assert() but c++0x only,
+ * Coverity also errors out. */
+#if (!defined(__cplusplus)) && \
+ (!defined(__COVERITY__)) && \
+ (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) /* gcc4.6+ only */
+# define BLI_STATIC_ASSERT(a, msg) __extension__ _Static_assert(a, msg);
+#else
+/* Code adapted from http://www.pixelbeat.org/programming/gcc/static_assert.html */
+/* Note we need the two concats below because arguments to ## are not expanded, so we need to
+ * expand __LINE__ with one indirection before doing the actual concatenation. */
+# define _BLI_ASSERT_CONCAT_(a, b) a##b
+# define _BLI_ASSERT_CONCAT(a, b) _BLI_ASSERT_CONCAT_(a, b)
+ /* These can't be used after statements in c89. */
+# if defined(__COUNTER__) /* MSVC */
+# define BLI_STATIC_ASSERT(a, msg) \
+ ; enum { _BLI_ASSERT_CONCAT(static_assert_, __COUNTER__) = 1 / (int)(!!(a)) };
+# else /* older gcc, clang... */
+ /* This can't be used twice on the same line so ensure if using in headers
+ * that the headers are not included twice (by wrapping in #ifndef...#endif)
+ * Note it doesn't cause an issue when used on same line of separate modules
+ * compiled with gcc -combine -fwhole-program. */
+# define BLI_STATIC_ASSERT(a, msg) \
+ ; enum { _BLI_ASSERT_CONCAT(assert_line_, __LINE__) = 1 / (int)(!!(a)) };
+# endif
+#endif
+
+#define BLI_STATIC_ASSERT_ALIGN(st, align) \
+ BLI_STATIC_ASSERT((sizeof(st) % (align) == 0), "Structure must be strictly aligned")
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BLI_ASSERT_H__ */
diff --git a/source/blender/blenlib/BLI_boxpack2d.h b/source/blender/blenlib/BLI_boxpack_2d.h
index b02e3423f88..80e89bdb04f 100644
--- a/source/blender/blenlib/BLI_boxpack2d.h
+++ b/source/blender/blenlib/BLI_boxpack_2d.h
@@ -25,10 +25,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __BLI_BOXPACK2D_H__
-#define __BLI_BOXPACK2D_H__
+#ifndef __BLI_BOXPACK_2D_H__
+#define __BLI_BOXPACK_2D_H__
-/** \file BLI_boxpack2d.h
+/** \file BLI_boxpack_2d.h
* \ingroup bli
*/
@@ -39,7 +39,7 @@ typedef struct BoxPack {
float y;
float w;
float h;
-
+
/* Verts this box uses
* (BL,TR,TL,BR) / 0,1,2,3 */
struct BoxVert *v[4];
@@ -49,5 +49,5 @@ typedef struct BoxPack {
void BLI_box_pack_2d(BoxPack *boxarray, const unsigned int len, float *tot_width, float *tot_height);
-#endif
+#endif /* __BLI_BOXPACK_2D_H__ */
diff --git a/source/blender/blenlib/BLI_buffer.h b/source/blender/blenlib/BLI_buffer.h
index 0c0845daf19..0d2ef0dc9b3 100644
--- a/source/blender/blenlib/BLI_buffer.h
+++ b/source/blender/blenlib/BLI_buffer.h
@@ -77,7 +77,7 @@ enum {
(BLI_buffer_at(buffer_, type_, (buffer_)->count - 1) = val_) \
)
-#define BLI_buffer_empty(buffer_) { \
+#define BLI_buffer_clear(buffer_) { \
(buffer_)->count = 0; \
} (void)0
diff --git a/source/blender/blenlib/BLI_console.h b/source/blender/blenlib/BLI_console.h
new file mode 100644
index 00000000000..bf433f78f70
--- /dev/null
+++ b/source/blender/blenlib/BLI_console.h
@@ -0,0 +1,42 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2018 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Srrgey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_CONSOLE_H__
+#define __BLI_CONSOLE_H__
+
+/** \file BLI_console.h
+ * \ingroup bli
+ * \brief Set of utility functions and constants to work with consoles.
+ */
+
+/* Format string where one could BLI_snprintf() R, G and B values
+ * and get proper marker to start colored output in the console.
+ */
+#define TRUECOLOR_ANSI_COLOR_FORMAT "\x1b[38;2;%d;%d;%dm"
+
+/* Marker which indicates that colored output is finished. */
+#define TRUECOLOR_ANSI_COLOR_FINISH "\x1b[0m"
+
+#endif /* __BLI_CONSOLE_H__ */
diff --git a/source/blender/blenlib/BLI_convexhull2d.h b/source/blender/blenlib/BLI_convexhull_2d.h
index 4b82071ede8..000d28acdde 100644
--- a/source/blender/blenlib/BLI_convexhull2d.h
+++ b/source/blender/blenlib/BLI_convexhull_2d.h
@@ -18,10 +18,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __BLI_CONVEXHULL2D_H__
-#define __BLI_CONVEXHULL2D_H__
+#ifndef __BLI_CONVEXHULL_2D_H__
+#define __BLI_CONVEXHULL_2D_H__
-/** \file BLI_convexhull2d.h
+/** \file BLI_convexhull_2d.h
* \ingroup bli
*/
@@ -31,4 +31,4 @@ int BLI_convexhull_2d(const float (*points)[2], const int n, int r_points[]);
float BLI_convexhull_aabb_fit_hull_2d(const float (*points_hull)[2], unsigned int n);
float BLI_convexhull_aabb_fit_points_2d(const float (*points)[2], unsigned int n);
-#endif /* __BLI_CONVEXHULL2D_H__ */
+#endif /* __BLI_CONVEXHULL_2D_H__ */
diff --git a/source/blender/blenlib/BLI_dial.h b/source/blender/blenlib/BLI_dial_2d.h
index 71ab57bb61a..dbd71a8ad3f 100644
--- a/source/blender/blenlib/BLI_dial.h
+++ b/source/blender/blenlib/BLI_dial_2d.h
@@ -18,10 +18,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __BLI_DIAL_H__
-#define __BLI_DIAL_H__
+#ifndef __BLI_DIAL_2D_H__
+#define __BLI_DIAL_2D_H__
-/** \file BLI_dial.h
+/** \file BLI_dial_2d.h
* \ingroup bli
*
* \note dials act similar to old rotation based phones and output an angle.
@@ -56,4 +56,4 @@ Dial *BLI_dial_initialize(const float start_position[2], float threshold);
float BLI_dial_angle(Dial *dial, const float current_position[2]);
-#endif /* __BLI_DIAL_H__ */
+#endif /* __BLI_DIAL_2D_H__ */
diff --git a/source/blender/blenlib/BLI_edgehash.h b/source/blender/blenlib/BLI_edgehash.h
index 20272dd97cd..41789201265 100644
--- a/source/blender/blenlib/BLI_edgehash.h
+++ b/source/blender/blenlib/BLI_edgehash.h
@@ -59,7 +59,7 @@ bool BLI_edgehash_remove(EdgeHash *eh, unsigned int v0, unsigned int
void *BLI_edgehash_popkey(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT;
bool BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT;
-int BLI_edgehash_size(EdgeHash *eh) ATTR_WARN_UNUSED_RESULT;
+int BLI_edgehash_len(EdgeHash *eh) ATTR_WARN_UNUSED_RESULT;
void BLI_edgehash_clear_ex(EdgeHash *eh, EdgeHashFreeFP valfreefp,
const unsigned int nentries_reserve);
void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp);
@@ -104,7 +104,7 @@ typedef struct EdgeSetIterator EdgeSetIterator;
EdgeSet *BLI_edgeset_new_ex(const char *info,
const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
EdgeSet *BLI_edgeset_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
-int BLI_edgeset_size(EdgeSet *es) ATTR_WARN_UNUSED_RESULT;
+int BLI_edgeset_len(EdgeSet *es) ATTR_WARN_UNUSED_RESULT;
bool BLI_edgeset_add(EdgeSet *es, unsigned int v0, unsigned int v1);
void BLI_edgeset_insert(EdgeSet *es, unsigned int v0, unsigned int v1);
bool BLI_edgeset_haskey(EdgeSet *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h
index 5c1fa57886a..bb23c63bdb3 100644
--- a/source/blender/blenlib/BLI_fileops.h
+++ b/source/blender/blenlib/BLI_fileops.h
@@ -35,6 +35,7 @@
#include <stdio.h>
#include <sys/stat.h>
+#include <stdint.h>
#ifdef __cplusplus
extern "C" {
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index b4819ff4e55..7003eb039dd 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -81,7 +81,10 @@ enum {
#endif
};
-/* *** */
+/** \name GHash API
+ *
+ * Defined in ``BLI_ghash.c``
+ * \{ */
GHash *BLI_ghash_new_ex(
GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info,
@@ -110,11 +113,14 @@ void BLI_ghash_clear_ex(
void *BLI_ghash_popkey(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp) ATTR_WARN_UNUSED_RESULT;
bool BLI_ghash_haskey(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT;
bool BLI_ghash_pop(GHash *gh, GHashIterState *state, void **r_key, void **r_val) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-unsigned int BLI_ghash_size(GHash *gh) ATTR_WARN_UNUSED_RESULT;
+unsigned int BLI_ghash_len(GHash *gh) ATTR_WARN_UNUSED_RESULT;
void BLI_ghash_flag_set(GHash *gh, unsigned int flag);
void BLI_ghash_flag_clear(GHash *gh, unsigned int flag);
-/* *** */
+/** \} */
+
+/** \name GHash Iterator
+ * \{ */
GHashIterator *BLI_ghashIterator_new(GHash *gh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
@@ -149,94 +155,15 @@ BLI_INLINE bool BLI_ghashIterator_done(GHashIterator *ghi) { return !ghi
BLI_ghashIterator_done(&gh_iter_) == false; \
BLI_ghashIterator_step(&gh_iter_), i_++)
-/** \name Callbacks for GHash
- *
- * \note '_p' suffix denotes void pointer arg,
- * so we can have functions that take correctly typed args too.
- * \{ */
-
-unsigned int BLI_ghashutil_ptrhash(const void *key);
-bool BLI_ghashutil_ptrcmp(const void *a, const void *b);
-
-unsigned int BLI_ghashutil_strhash_n(const char *key, size_t n);
-#define BLI_ghashutil_strhash(key) ( \
- CHECK_TYPE_ANY(key, char *, const char *, const char * const), \
- BLI_ghashutil_strhash_p(key))
-unsigned int BLI_ghashutil_strhash_p(const void *key);
-unsigned int BLI_ghashutil_strhash_p_murmur(const void *key);
-bool BLI_ghashutil_strcmp(const void *a, const void *b);
-
-#define BLI_ghashutil_inthash(key) ( \
- CHECK_TYPE_ANY(&(key), int *, const int *), \
- BLI_ghashutil_uinthash((unsigned int)key))
-unsigned int BLI_ghashutil_uinthash(unsigned int key);
-unsigned int BLI_ghashutil_inthash_p(const void *ptr);
-unsigned int BLI_ghashutil_inthash_p_murmur(const void *ptr);
-unsigned int BLI_ghashutil_inthash_p_simple(const void *ptr);
-bool BLI_ghashutil_intcmp(const void *a, const void *b);
-
-size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b);
-
-
-unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]);
-#define BLI_ghashutil_inthash_v4(key) ( \
- CHECK_TYPE_ANY(key, int *, const int *), \
- BLI_ghashutil_uinthash_v4((const unsigned int *)key))
-#define BLI_ghashutil_inthash_v4_p \
- ((GSetHashFP)BLI_ghashutil_uinthash_v4)
-#define BLI_ghashutil_uinthash_v4_p \
- ((GSetHashFP)BLI_ghashutil_uinthash_v4)
-unsigned int BLI_ghashutil_uinthash_v4_murmur(const unsigned int key[4]);
-#define BLI_ghashutil_inthash_v4_murmur(key) ( \
- CHECK_TYPE_ANY(key, int *, const int *), \
- BLI_ghashutil_uinthash_v4_murmur((const unsigned int *)key))
-#define BLI_ghashutil_inthash_v4_p_murmur \
- ((GSetHashFP)BLI_ghashutil_uinthash_v4_murmur)
-#define BLI_ghashutil_uinthash_v4_p_murmur \
- ((GSetHashFP)BLI_ghashutil_uinthash_v4_murmur)
-bool BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b);
-#define BLI_ghashutil_inthash_v4_cmp \
- BLI_ghashutil_uinthash_v4_cmp
-
/** \} */
-GHash *BLI_ghash_ptr_new_ex(
- const char *info,
- const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
-GHash *BLI_ghash_ptr_new(
- const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
-GHash *BLI_ghash_str_new_ex(
- const char *info,
- const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
-GHash *BLI_ghash_str_new(
- const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
-GHash *BLI_ghash_int_new_ex(
- const char *info,
- const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
-GHash *BLI_ghash_int_new(
- const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
-GHash *BLI_ghash_pair_new_ex(
- const char *info,
- const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
-GHash *BLI_ghash_pair_new(
- const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
-
-typedef struct GHashPair {
- const void *first;
- const void *second;
-} GHashPair;
-
-GHashPair *BLI_ghashutil_pairalloc(const void *first, const void *second);
-unsigned int BLI_ghashutil_pairhash(const void *ptr);
-bool BLI_ghashutil_paircmp(const void *a, const void *b);
-void BLI_ghashutil_pairfree(void *ptr);
-
-/**
- * GSet is a 'set' implementation (unordered collection of unique elements).
+/** \name GSet API
+ * A 'set' implementation (unordered collection of unique elements).
*
* Internally this is a 'GHash' without any keys,
* which is why this API's are in the same header & source file.
- */
+ *
+ * \{ */
typedef struct GSet GSet;
@@ -247,21 +174,12 @@ typedef GHashKeyCopyFP GSetKeyCopyFP;
typedef GHashIterState GSetIterState;
-/* so we can cast but compiler sees as different */
-typedef struct GSetIterator {
- GHashIterator _ghi
-#ifdef __GNUC__
- __attribute__ ((deprecated))
-#endif
- ;
-} GSetIterator;
-
GSet *BLI_gset_new_ex(
GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info,
const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
GSet *BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
GSet *BLI_gset_copy(GSet *gs, GSetKeyCopyFP keycopyfp) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
-unsigned int BLI_gset_size(GSet *gs) ATTR_WARN_UNUSED_RESULT;
+unsigned int BLI_gset_len(GSet *gs) ATTR_WARN_UNUSED_RESULT;
void BLI_gset_flag_set(GSet *gs, unsigned int flag);
void BLI_gset_flag_clear(GSet *gs, unsigned int flag);
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp);
@@ -281,14 +199,22 @@ void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp);
void *BLI_gset_lookup(GSet *gh, const void *key) ATTR_WARN_UNUSED_RESULT;
void *BLI_gset_pop_key(GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT;
-GSet *BLI_gset_ptr_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
-GSet *BLI_gset_ptr_new(const char *info);
-GSet *BLI_gset_str_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
-GSet *BLI_gset_str_new(const char *info);
-GSet *BLI_gset_pair_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
-GSet *BLI_gset_pair_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+/** \} */
+
+/** \name GSet Iterator
+ * \{ */
/* rely on inline api for now */
+
+/* so we can cast but compiler sees as different */
+typedef struct GSetIterator {
+ GHashIterator _ghi
+#ifdef __GNUC__
+ __attribute__ ((deprecated))
+#endif
+ ;
+} GSetIterator;
+
BLI_INLINE GSetIterator *BLI_gsetIterator_new(GSet *gs) { return (GSetIterator *)BLI_ghashIterator_new((GHash *)gs); }
BLI_INLINE void BLI_gsetIterator_init(GSetIterator *gsi, GSet *gs) { BLI_ghashIterator_init((GHashIterator *)gsi, (GHash *)gs); }
BLI_INLINE void BLI_gsetIterator_free(GSetIterator *gsi) { BLI_ghashIterator_free((GHashIterator *)gsi); }
@@ -306,11 +232,15 @@ BLI_INLINE bool BLI_gsetIterator_done(GSetIterator *gsi) { return BLI_ghashItera
BLI_gsetIterator_done(&gs_iter_) == false; \
BLI_gsetIterator_step(&gs_iter_), i_++)
+/** \} */
+
+/** \name GHash/GSet Debugging API's
+ * \{ */
/* For testing, debugging only */
#ifdef GHASH_INTERNAL_API
-int BLI_ghash_buckets_size(GHash *gh);
-int BLI_gset_buckets_size(GSet *gs);
+int BLI_ghash_buckets_len(GHash *gh);
+int BLI_gset_buckets_len(GSet *gs);
double BLI_ghash_calc_quality_ex(
GHash *gh, double *r_load, double *r_variance,
@@ -321,6 +251,10 @@ double BLI_gset_calc_quality_ex(
double BLI_ghash_calc_quality(GHash *gh);
double BLI_gset_calc_quality(GSet *gs);
#endif /* GHASH_INTERNAL_API */
+/** \} */
+
+/** \name GHash/GSet Macros
+ * \{ */
#define GHASH_FOREACH_BEGIN(type, var, what) \
do { \
@@ -342,6 +276,113 @@ double BLI_gset_calc_quality(GSet *gs);
} \
} while(0)
+/** \} */
+
+/** \name GHash/GSet Utils
+ *
+ * Defined in ``BLI_ghash_utils.c``
+ * \{ */
+
+/**
+ * Callbacks for GHash (``BLI_ghashutil_``)
+ *
+ * \note '_p' suffix denotes void pointer arg,
+ * so we can have functions that take correctly typed args too.
+ */
+
+unsigned int BLI_ghashutil_ptrhash(const void *key);
+bool BLI_ghashutil_ptrcmp(const void *a, const void *b);
+
+unsigned int BLI_ghashutil_strhash_n(const char *key, size_t n);
+#define BLI_ghashutil_strhash(key) ( \
+ CHECK_TYPE_ANY(key, char *, const char *, const char * const), \
+ BLI_ghashutil_strhash_p(key))
+unsigned int BLI_ghashutil_strhash_p(const void *key);
+unsigned int BLI_ghashutil_strhash_p_murmur(const void *key);
+bool BLI_ghashutil_strcmp(const void *a, const void *b);
+
+#define BLI_ghashutil_inthash(key) ( \
+ CHECK_TYPE_ANY(&(key), int *, const int *), \
+ BLI_ghashutil_uinthash((unsigned int)key))
+unsigned int BLI_ghashutil_uinthash(unsigned int key);
+unsigned int BLI_ghashutil_inthash_p(const void *ptr);
+unsigned int BLI_ghashutil_inthash_p_murmur(const void *ptr);
+unsigned int BLI_ghashutil_inthash_p_simple(const void *ptr);
+bool BLI_ghashutil_intcmp(const void *a, const void *b);
+
+size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b);
+
+
+unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]);
+#define BLI_ghashutil_inthash_v4(key) ( \
+ CHECK_TYPE_ANY(key, int *, const int *), \
+ BLI_ghashutil_uinthash_v4((const unsigned int *)key))
+#define BLI_ghashutil_inthash_v4_p \
+ ((GSetHashFP)BLI_ghashutil_uinthash_v4)
+#define BLI_ghashutil_uinthash_v4_p \
+ ((GSetHashFP)BLI_ghashutil_uinthash_v4)
+unsigned int BLI_ghashutil_uinthash_v4_murmur(const unsigned int key[4]);
+#define BLI_ghashutil_inthash_v4_murmur(key) ( \
+ CHECK_TYPE_ANY(key, int *, const int *), \
+ BLI_ghashutil_uinthash_v4_murmur((const unsigned int *)key))
+#define BLI_ghashutil_inthash_v4_p_murmur \
+ ((GSetHashFP)BLI_ghashutil_uinthash_v4_murmur)
+#define BLI_ghashutil_uinthash_v4_p_murmur \
+ ((GSetHashFP)BLI_ghashutil_uinthash_v4_murmur)
+bool BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b);
+#define BLI_ghashutil_inthash_v4_cmp \
+ BLI_ghashutil_uinthash_v4_cmp
+
+typedef struct GHashPair {
+ const void *first;
+ const void *second;
+} GHashPair;
+
+GHashPair *BLI_ghashutil_pairalloc(const void *first, const void *second);
+unsigned int BLI_ghashutil_pairhash(const void *ptr);
+bool BLI_ghashutil_paircmp(const void *a, const void *b);
+void BLI_ghashutil_pairfree(void *ptr);
+
+/**
+ * Wrapper GHash Creation Functions
+ */
+
+GHash *BLI_ghash_ptr_new_ex(
+ const char *info,
+ const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GHash *BLI_ghash_ptr_new(
+ const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GHash *BLI_ghash_str_new_ex(
+ const char *info,
+ const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GHash *BLI_ghash_str_new(
+ const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GHash *BLI_ghash_int_new_ex(
+ const char *info,
+ const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GHash *BLI_ghash_int_new(
+ const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GHash *BLI_ghash_pair_new_ex(
+ const char *info,
+ const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GHash *BLI_ghash_pair_new(
+ const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+
+GSet *BLI_gset_ptr_new_ex(
+ const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GSet *BLI_gset_ptr_new(
+ const char *info);
+GSet *BLI_gset_str_new_ex(
+ const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GSet *BLI_gset_str_new(
+ const char *info);
+GSet *BLI_gset_pair_new_ex(
+ const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GSet *BLI_gset_pair_new(
+ const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+
+/** \} */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_gsqueue.h b/source/blender/blenlib/BLI_gsqueue.h
index 4600d6f6325..ef0e0f3ab31 100644
--- a/source/blender/blenlib/BLI_gsqueue.h
+++ b/source/blender/blenlib/BLI_gsqueue.h
@@ -36,11 +36,11 @@ typedef struct _GSQueue GSQueue;
GSQueue *BLI_gsqueue_new(size_t elem_size);
bool BLI_gsqueue_is_empty(GSQueue *gq);
-int BLI_gsqueue_size(GSQueue *gq);
+int BLI_gsqueue_len(GSQueue *gq);
void BLI_gsqueue_peek(GSQueue *gq, void *r_item);
void BLI_gsqueue_pop(GSQueue *gq, void *r_item);
void BLI_gsqueue_push(GSQueue *gq, const void *item);
-void BLI_gsqueue_pushback(GSQueue *gq, const void *item);
+void BLI_gsqueue_push_back(GSQueue *gq, const void *item);
void BLI_gsqueue_free(GSQueue *gq);
#endif /* __BLI_GSQUEUE_H__ */
diff --git a/source/blender/blenlib/BLI_hash.h b/source/blender/blenlib/BLI_hash.h
index e849e5f8f61..f74010479a9 100644
--- a/source/blender/blenlib/BLI_hash.h
+++ b/source/blender/blenlib/BLI_hash.h
@@ -63,4 +63,21 @@ BLI_INLINE unsigned int BLI_hash_int(unsigned int k)
return BLI_hash_int_2d(k, 0);
}
+BLI_INLINE float BLI_hash_int_01(unsigned int k)
+{
+ return (float)BLI_hash_int(k) * (1.0f / (float)0xFFFFFFFF);
+}
+
+BLI_INLINE void BLI_hash_pointer_to_color(const void *ptr, int *r, int *g, int *b)
+{
+ size_t val = (size_t)ptr;
+ const size_t hash_a = BLI_hash_int(val & 0x0000ffff);
+ const size_t hash_b = BLI_hash_int((uint)((val & 0xffff0000) >> 32));
+ const size_t hash =
+ hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2));
+ *r = (hash & 0xff0000) >> 16;
+ *g = (hash & 0x00ff00) >> 8;
+ *b = hash & 0x0000ff;
+}
+
#endif // __BLI_HASH_H__
diff --git a/source/blender/blenlib/BLI_heap.h b/source/blender/blenlib/BLI_heap.h
index d3f6d44e164..19e162d777f 100644
--- a/source/blender/blenlib/BLI_heap.h
+++ b/source/blender/blenlib/BLI_heap.h
@@ -41,9 +41,9 @@ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr) ATTR_NONNULL
void BLI_heap_insert_or_update(Heap *heap, HeapNode **node_p, float value, void *ptr) ATTR_NONNULL(1, 2);
void BLI_heap_remove(Heap *heap, HeapNode *node) ATTR_NONNULL(1, 2);
bool BLI_heap_is_empty(const Heap *heap) ATTR_NONNULL(1);
-unsigned int BLI_heap_size(const Heap *heap) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+unsigned int BLI_heap_len(const Heap *heap) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
HeapNode *BLI_heap_top(const Heap *heap) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
-void *BLI_heap_popmin(Heap *heap) ATTR_NONNULL(1);
+void *BLI_heap_pop_min(Heap *heap) ATTR_NONNULL(1);
void BLI_heap_node_value_update(Heap *heap, HeapNode *node, float value) ATTR_NONNULL(1, 2);
void BLI_heap_node_value_update_ptr(Heap *heap, HeapNode *node, float value, void *ptr) ATTR_NONNULL(1, 2);
diff --git a/source/blender/blenlib/BLI_iterator.h b/source/blender/blenlib/BLI_iterator.h
index 49a3cea58bc..d3d375122a1 100644
--- a/source/blender/blenlib/BLI_iterator.h
+++ b/source/blender/blenlib/BLI_iterator.h
@@ -57,6 +57,6 @@ typedef void (*IteratorBeginCb)(BLI_Iterator *iter, void *data_in);
#define ITER_END \
} \
callback_end_func(&iter_macro); \
-}
+} ((void)0)
#endif /* __BLI_ITERATOR_H__ */
diff --git a/source/blender/blenlib/BLI_jitter.h b/source/blender/blenlib/BLI_jitter_2d.h
index 769fb445678..e2b1f21800c 100644
--- a/source/blender/blenlib/BLI_jitter.h
+++ b/source/blender/blenlib/BLI_jitter_2d.h
@@ -25,10 +25,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __BLI_JITTER_H__
-#define __BLI_JITTER_H__
+#ifndef __BLI_JITTER_2D_H__
+#define __BLI_JITTER_2D_H__
-/** \file BLI_jitter.h
+/** \file BLI_jitter_2d.h
* \ingroup bli
*/
@@ -36,5 +36,5 @@ void BLI_jitter_init(float (*jitarr)[2], int num);
void BLI_jitterate1(float (*jit1)[2], float (*jit2)[2], int num, float radius1);
void BLI_jitterate2(float (*jit1)[2], float (*jit2)[2], int num, float radius2);
-#endif
+#endif /* __BLI_JITTER_2D_H__ */
diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h
index 564659ad21e..db53035dc7b 100644
--- a/source/blender/blenlib/BLI_kdopbvh.h
+++ b/source/blender/blenlib/BLI_kdopbvh.h
@@ -129,7 +129,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(
const BVHTree *tree1, const BVHTree *tree2, unsigned int *r_overlap_tot,
BVHTree_OverlapCallback callback, void *userdata);
-int BLI_bvhtree_get_size(const BVHTree *tree);
+int BLI_bvhtree_get_len(const BVHTree *tree);
float BLI_bvhtree_get_epsilon(const BVHTree *tree);
diff --git a/source/blender/blenlib/BLI_lasso.h b/source/blender/blenlib/BLI_lasso_2d.h
index 28f21e5bd85..3644224f1d7 100644
--- a/source/blender/blenlib/BLI_lasso.h
+++ b/source/blender/blenlib/BLI_lasso_2d.h
@@ -25,10 +25,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __BLI_LASSO_H__
-#define __BLI_LASSO_H__
+#ifndef __BLI_LASSO_2D_H__
+#define __BLI_LASSO_2D_H__
-/** \file BLI_lasso.h
+/** \file BLI_lasso_2d.h
* \ingroup bli
*/
@@ -38,4 +38,4 @@ void BLI_lasso_boundbox(struct rcti *rect, const int mcords[][2], const unsigned
bool BLI_lasso_is_point_inside(const int mcords[][2], const unsigned int moves, const int sx, const int sy, const int error_value);
bool BLI_lasso_is_edge_inside(const int mcords[][2], const unsigned int moves, int x0, int y0, int x1, int y1, const int error_value);
-#endif
+#endif /* __BLI_LASSO_2D_H__ */
diff --git a/source/blender/blenlib/BLI_link_utils.h b/source/blender/blenlib/BLI_link_utils.h
index d469b105f93..5322547ac08 100644
--- a/source/blender/blenlib/BLI_link_utils.h
+++ b/source/blender/blenlib/BLI_link_utils.h
@@ -35,6 +35,18 @@
list = link; \
} (void)0
+/* Use for append (single linked list, storing the last element). */
+#define BLI_LINKS_APPEND(list, link) { \
+ (link)->next = NULL; \
+ if ((list)->first) { \
+ (list)->last->next = link; \
+ } \
+ else { \
+ (list)->first = link; \
+ } \
+ (list)->last = link; \
+} (void)0
+
#define BLI_LINKS_FREE(list) { \
while (list) { \
void *next = list->next; \
diff --git a/source/blender/blenlib/BLI_linklist_stack.h b/source/blender/blenlib/BLI_linklist_stack.h
index dd92dcec936..dd6d737f111 100644
--- a/source/blender/blenlib/BLI_linklist_stack.h
+++ b/source/blender/blenlib/BLI_linklist_stack.h
@@ -60,7 +60,7 @@
} (void)0
#define BLI_LINKSTACK_SIZE(var) \
- BLI_mempool_count(var##_pool_)
+ BLI_mempool_len(var##_pool_)
/* check for typeof() */
#ifdef __GNUC__
diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h
index 2a0f4e6f814..c4ad5acfe4b 100644
--- a/source/blender/blenlib/BLI_listbase.h
+++ b/source/blender/blenlib/BLI_listbase.h
@@ -74,7 +74,7 @@ void BLI_listbase_sort(struct ListBase *listbase, int (*cmp)(const void *, const
void BLI_listbase_sort_r(ListBase *listbase, int (*cmp)(void *, const void *, const void *), void *thunk) ATTR_NONNULL(1, 2);
bool BLI_listbase_link_move(ListBase *listbase, void *vlink, int step) ATTR_NONNULL();
void BLI_freelist(struct ListBase *listbase) ATTR_NONNULL(1);
-int BLI_listbase_count_ex(const struct ListBase *listbase, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+int BLI_listbase_count_at_most(const struct ListBase *listbase, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);
@@ -103,32 +103,33 @@ struct LinkData *BLI_genericNodeN(void *data);
*
* \code{.c}
*
- * BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN (listbase, item, item_init) {
+ * LISTBASE_CIRCULAR_FORWARD_BEGIN(listbase, item, item_init)
+ * {
* ...operate on marker...
* }
- * BLI_LISTBASE_CIRCULAR_FORWARD_END (listbase, item, item_init);
+ * LISTBASE_CIRCULAR_FORWARD_END (listbase, item, item_init);
*
* \endcode
*/
-#define BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN(lb, lb_iter, lb_init) \
+#define LISTBASE_CIRCULAR_FORWARD_BEGIN(lb, lb_iter, lb_init) \
if ((lb)->first && (lb_init || (lb_init = (lb)->first))) { \
lb_iter = lb_init; \
do {
-#define BLI_LISTBASE_CIRCULAR_FORWARD_END(lb, lb_iter, lb_init) \
+#define LISTBASE_CIRCULAR_FORWARD_END(lb, lb_iter, lb_init) \
} while ((lb_iter = (lb_iter)->next ? (lb_iter)->next : (lb)->first), \
(lb_iter != lb_init)); \
}
-#define BLI_LISTBASE_CIRCULAR_BACKWARD_BEGIN(lb, lb_iter, lb_init) \
+#define LISTBASE_CIRCULAR_BACKWARD_BEGIN(lb, lb_iter, lb_init) \
if ((lb)->last && (lb_init || (lb_init = (lb)->last))) { \
lb_iter = lb_init; \
do {
-#define BLI_LISTBASE_CIRCULAR_BACKWARD_END(lb, lb_iter, lb_init) \
+#define LISTBASE_CIRCULAR_BACKWARD_END(lb, lb_iter, lb_init) \
} while ((lb_iter = (lb_iter)->prev ? (lb_iter)->prev : (lb)->last), \
(lb_iter != lb_init)); \
}
-#define BLI_LISTBASE_FOREACH(type, var, list) \
+#define LISTBASE_FOREACH(type, var, list) \
for (type var = (type)((list)->first); \
var != NULL; \
var = (type)(((Link*)(var))->next))
diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h
index 377b9325717..6f8e48d83b2 100644
--- a/source/blender/blenlib/BLI_math_base.h
+++ b/source/blender/blenlib/BLI_math_base.h
@@ -35,6 +35,7 @@
#endif
#include <math.h>
+#include "BLI_assert.h"
#include "BLI_math_inline.h"
#ifndef M_PI
@@ -132,6 +133,10 @@ MINLINE int max_iiii(int a, int b, int c, int d);
MINLINE size_t min_zz(size_t a, size_t b);
MINLINE size_t max_zz(size_t a, size_t b);
+MINLINE int clamp_i(int value, int min, int max);
+MINLINE float clamp_f(float value, float min, float max);
+MINLINE size_t clamp_z(size_t value, size_t min, size_t max);
+
MINLINE int compare_ff(float a, float b, const float max_diff);
MINLINE int compare_ff_relative(float a, float b, const float max_diff, const int max_ulps);
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index 060d2e27740..d58e3022e27 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -85,6 +85,7 @@ bool is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3],
bool is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2]);
bool is_poly_convex_v2(const float verts[][2], unsigned int nr);
int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
+bool is_quad_flip_v3_first_third_fast(const float v0[3], const float v1[3], const float v2[3], const float v3[3]);
/********************************* Distance **********************************/
diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h
index b68ca6b1f2b..45efb8d7ef1 100644
--- a/source/blender/blenlib/BLI_mempool.h
+++ b/source/blender/blenlib/BLI_mempool.h
@@ -53,7 +53,7 @@ void BLI_mempool_clear_ex(BLI_mempool *pool,
const int totelem_reserve) ATTR_NONNULL(1);
void BLI_mempool_clear(BLI_mempool *pool) ATTR_NONNULL(1);
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1);
-int BLI_mempool_count(BLI_mempool *pool) ATTR_NONNULL(1);
+int BLI_mempool_len(BLI_mempool *pool) ATTR_NONNULL(1);
void *BLI_mempool_findelem(BLI_mempool *pool, unsigned int index) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
void BLI_mempool_as_table(BLI_mempool *pool, void **data) ATTR_NONNULL(1, 2);
diff --git a/source/blender/blenlib/BLI_polyfill2d.h b/source/blender/blenlib/BLI_polyfill_2d.h
index 798055f9240..099f08d4663 100644
--- a/source/blender/blenlib/BLI_polyfill2d.h
+++ b/source/blender/blenlib/BLI_polyfill_2d.h
@@ -18,8 +18,8 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __BLI_POLYFILL2D_H__
-#define __BLI_POLYFILL2D_H__
+#ifndef __BLI_POLYFILL_2D_H__
+#define __BLI_POLYFILL_2D_H__
struct MemArena;
@@ -40,4 +40,4 @@ void BLI_polyfill_calc(
/* default size of polyfill arena */
#define BLI_POLYFILL_ARENA_SIZE MEM_SIZE_OPTIMAL(1 << 14)
-#endif /* __BLI_POLYFILL2D_H__ */
+#endif /* __BLI_POLYFILL_2D_H__ */
diff --git a/source/blender/blenlib/BLI_polyfill2d_beautify.h b/source/blender/blenlib/BLI_polyfill_2d_beautify.h
index 278771e9611..73b52125904 100644
--- a/source/blender/blenlib/BLI_polyfill2d_beautify.h
+++ b/source/blender/blenlib/BLI_polyfill_2d_beautify.h
@@ -18,8 +18,8 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __BLI_POLYFILL2D_BEAUTIFY_H__
-#define __BLI_POLYFILL2D_BEAUTIFY_H__
+#ifndef __BLI_POLYFILL_2D_BEAUTIFY_H__
+#define __BLI_POLYFILL_2D_BEAUTIFY_H__
struct Heap;
struct MemArena;
@@ -42,4 +42,4 @@ float BLI_polyfill_beautify_quad_rotate_calc_ex(
/* avoid realloc's when creating new structures for polyfill ngons */
#define BLI_POLYFILL_ALLOC_NGON_RESERVE 64
-#endif /* __BLI_POLYFILL2D_BEAUTIFY_H__ */
+#endif /* __BLI_POLYFILL_2D_BEAUTIFY_H__ */
diff --git a/source/blender/blenlib/BLI_smallhash.h b/source/blender/blenlib/BLI_smallhash.h
index e096354e5b1..495fc94a53c 100644
--- a/source/blender/blenlib/BLI_smallhash.h
+++ b/source/blender/blenlib/BLI_smallhash.h
@@ -66,7 +66,7 @@ bool BLI_smallhash_remove(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
void *BLI_smallhash_lookup(const SmallHash *sh, uintptr_t key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
void **BLI_smallhash_lookup_p(const SmallHash *sh, uintptr_t key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
bool BLI_smallhash_haskey(const SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
-int BLI_smallhash_count(const SmallHash *sh) ATTR_NONNULL(1);
+int BLI_smallhash_len(const SmallHash *sh) ATTR_NONNULL(1);
void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
void **BLI_smallhash_iternext_p(SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
void *BLI_smallhash_iternew(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/blenlib/BLI_sort_utils.h b/source/blender/blenlib/BLI_sort_utils.h
index e08f4e5ac83..f6bd80b30d3 100644
--- a/source/blender/blenlib/BLI_sort_utils.h
+++ b/source/blender/blenlib/BLI_sort_utils.h
@@ -32,7 +32,7 @@
* \note keep \a sort_value first,
* so cmp functions can be reused.
*/
-struct SortPointerByFloat {
+struct SortPtrByFloat {
float sort_value;
void *data;
};
@@ -42,7 +42,7 @@ struct SortIntByFloat {
int data;
};
-struct SortPointerByInt {
+struct SortPtrByInt {
int sort_value;
void *data;
};
@@ -58,4 +58,7 @@ int BLI_sortutil_cmp_float_reverse(const void *a_, const void *b_);
int BLI_sortutil_cmp_int(const void *a_, const void *b_);
int BLI_sortutil_cmp_int_reverse(const void *a_, const void *b_);
+int BLI_sortutil_cmp_ptr(const void *a_, const void *b_);
+int BLI_sortutil_cmp_ptr_reverse(const void *a_, const void *b_);
+
#endif /* __BLI_SORT_UTILS_H__ */
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index d137806c575..48be9d1842f 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -103,6 +103,20 @@ int BLI_string_find_split_words(
const char delim, int r_words[][2], int words_max)
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/** \name String Copy/Format Macros
+ * Avoid repeating destination with `sizeof(..)`.
+ * \note `ARRAY_SIZE` allows pointers on some platforms.
+ * \{ */
+#define STRNCPY(dst, src) \
+ BLI_strncpy(dst, src, ARRAY_SIZE(dst))
+#define STRNCPY_RLEN(dst, src) \
+ BLI_strncpy_rlen(dst, src, ARRAY_SIZE(dst))
+#define SNPRINTF(dst, format, ...) \
+ BLI_snprintf(dst, ARRAY_SIZE(dst), format, __VA_ARGS__)
+#define SNPRINTF_RLEN(dst, format, ...) \
+ BLI_snprintf_rlen(dst, ARRAY_SIZE(dst), format, __VA_ARGS__)
+/** \} */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h
index 32504a88b48..21542d0d6e1 100644
--- a/source/blender/blenlib/BLI_string_utf8.h
+++ b/source/blender/blenlib/BLI_string_utf8.h
@@ -77,6 +77,16 @@ size_t BLI_str_partition_ex_utf8(
#define BLI_UTF8_WIDTH_MAX 2 /* columns */
#define BLI_UTF8_ERR ((unsigned int)-1)
+/** \name String Copy/Format Macros
+ * Avoid repeating destination with `sizeof(..)`.
+ * \note `ARRAY_SIZE` allows pointers on some platforms.
+ * \{ */
+#define STRNCPY_UTF8(dst, src) \
+ BLI_strncpy_utf8(dst, src, ARRAY_SIZE(dst))
+#define STRNCPY_UTF8_RLEN(dst, src) \
+ BLI_strncpy_utf8_rlen(dst, src, ARRAY_SIZE(dst))
+/** \} */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h
index 60da6b39cbe..66eb5cfd22b 100644
--- a/source/blender/blenlib/BLI_threads.h
+++ b/source/blender/blenlib/BLI_threads.h
@@ -55,19 +55,19 @@ void BLI_threadapi_exit(void);
struct TaskScheduler *BLI_task_scheduler_get(void);
-void BLI_init_threads(struct ListBase *threadbase, void *(*do_thread)(void *), int tot);
+void BLI_threadpool_init(struct ListBase *threadbase, void *(*do_thread)(void *), int tot);
int BLI_available_threads(struct ListBase *threadbase);
-int BLI_available_thread_index(struct ListBase *threadbase);
-void BLI_insert_thread(struct ListBase *threadbase, void *callerdata);
-void BLI_remove_thread(struct ListBase *threadbase, void *callerdata);
-void BLI_remove_thread_index(struct ListBase *threadbase, int index);
-void BLI_remove_threads(struct ListBase *threadbase);
-void BLI_end_threads(struct ListBase *threadbase);
+int BLI_threadpool_available_thread_index(struct ListBase *threadbase);
+void BLI_threadpool_insert(struct ListBase *threadbase, void *callerdata);
+void BLI_threadpool_remove(struct ListBase *threadbase, void *callerdata);
+void BLI_threadpool_remove_index(struct ListBase *threadbase, int index);
+void BLI_threadpool_clear(struct ListBase *threadbase);
+void BLI_threadpool_end(struct ListBase *threadbase);
int BLI_thread_is_main(void);
-void BLI_begin_threaded_malloc(void);
-void BLI_end_threaded_malloc(void);
+void BLI_threaded_malloc_begin(void);
+void BLI_threaded_malloc_end(void);
/* System Information */
@@ -91,8 +91,8 @@ int BLI_system_num_threads_override_get(void);
#define LOCK_FFTW 9
#define LOCK_VIEW3D 10
-void BLI_lock_thread(int type);
-void BLI_unlock_thread(int type);
+void BLI_thread_lock(int type);
+void BLI_thread_unlock(int type);
/* Mutex Lock */
@@ -177,7 +177,7 @@ void BLI_thread_queue_free(ThreadQueue *queue);
void BLI_thread_queue_push(ThreadQueue *queue, void *work);
void *BLI_thread_queue_pop(ThreadQueue *queue);
void *BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms);
-int BLI_thread_queue_size(ThreadQueue *queue);
+int BLI_thread_queue_len(ThreadQueue *queue);
bool BLI_thread_queue_is_empty(ThreadQueue *queue);
void BLI_thread_queue_wait_finish(ThreadQueue *queue);
diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index ee1acc5afdd..46b3748c7ce 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -41,9 +41,8 @@ extern "C" {
#include "BLI_compiler_compat.h"
#include "BLI_utildefines_variadic.h"
-#ifndef NDEBUG /* for BLI_assert */
-#include <stdio.h>
-#endif
+/* We could remove in future. */
+#include "BLI_assert.h"
/* useful for finding bad use of min/max */
#if 0
@@ -412,7 +411,7 @@ extern "C" {
} (void)0
/* assuming a static array */
-#if defined(__GNUC__) && !defined(__cplusplus) && !defined(__clang__)
+#if defined(__GNUC__) && !defined(__cplusplus) && !defined(__clang__) && !defined(__INTEL_COMPILER)
# define ARRAY_SIZE(arr) \
((sizeof(struct {int isnt_array : ((const void *)&(arr) == &(arr)[0]);}) * 0) + \
(sizeof(arr) / sizeof(*(arr))))
@@ -615,74 +614,6 @@ extern bool BLI_memory_is_zero(const void *arr, const size_t arr_size);
# define UNUSED_VARS_NDEBUG UNUSED_VARS
#endif
-
-/* BLI_assert(), default only to print
- * for aborting need to define WITH_ASSERT_ABORT
- */
-/* For 'abort' only. */
-#include <stdlib.h>
-
-#ifndef NDEBUG
-# include "BLI_system.h"
-# ifdef WITH_ASSERT_ABORT
-# define _BLI_DUMMY_ABORT abort
-# else
-# define _BLI_DUMMY_ABORT() (void)0
-# endif
-# if defined(__GNUC__) || defined(_MSC_VER) /* check __func__ is available */
-# define BLI_assert(a) \
- (void)((!(a)) ? ( \
- ( \
- BLI_system_backtrace(stderr), \
- fprintf(stderr, \
- "BLI_assert failed: %s:%d, %s(), at \'%s\'\n", \
- __FILE__, __LINE__, __func__, STRINGIFY(a)), \
- _BLI_DUMMY_ABORT(), \
- NULL)) : NULL)
-# else
-# define BLI_assert(a) \
- (void)((!(a)) ? ( \
- ( \
- fprintf(stderr, \
- "BLI_assert failed: %s:%d, at \'%s\'\n", \
- __FILE__, __LINE__, STRINGIFY(a)), \
- _BLI_DUMMY_ABORT(), \
- NULL)) : NULL)
-# endif
-#else
-# define BLI_assert(a) (void)0
-#endif
-
-/* C++ can't use _Static_assert, expects static_assert() but c++0x only,
- * Coverity also errors out. */
-#if (!defined(__cplusplus)) && \
- (!defined(__COVERITY__)) && \
- (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) /* gcc4.6+ only */
-# define BLI_STATIC_ASSERT(a, msg) __extension__ _Static_assert(a, msg);
-#else
-/* Code adapted from http://www.pixelbeat.org/programming/gcc/static_assert.html */
-/* Note we need the two concats below because arguments to ## are not expanded, so we need to
- * expand __LINE__ with one indirection before doing the actual concatenation. */
-# define ASSERT_CONCAT_(a, b) a##b
-# define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
- /* These can't be used after statements in c89. */
-# if defined(__COUNTER__) /* MSVC */
-# define BLI_STATIC_ASSERT(a, msg) \
- ; enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1 / (int)(!!(a)) };
-# else /* older gcc, clang... */
- /* This can't be used twice on the same line so ensure if using in headers
- * that the headers are not included twice (by wrapping in #ifndef...#endif)
- * Note it doesn't cause an issue when used on same line of separate modules
- * compiled with gcc -combine -fwhole-program. */
-# define BLI_STATIC_ASSERT(a, msg) \
- ; enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1 / (int)(!!(a)) };
-# endif
-#endif
-
-
-#define BLI_STATIC_ASSERT_ALIGN(st, align) \
- BLI_STATIC_ASSERT((sizeof(st) % (align) == 0), "Structure must be strictly aligned")
-
/* hints for branch prediction, only use in code that runs a _lot_ where */
#ifdef __GNUC__
# define LIKELY(x) __builtin_expect(!!(x), 1)
diff --git a/source/blender/blenlib/BLI_voronoi.h b/source/blender/blenlib/BLI_voronoi_2d.h
index 9d32061bf97..8d1ff2d4c2b 100644
--- a/source/blender/blenlib/BLI_voronoi.h
+++ b/source/blender/blenlib/BLI_voronoi_2d.h
@@ -23,12 +23,12 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __BLI_VORONOI_H__
-#define __BLI_VORONOI_H__
+#ifndef __BLI_VORONOI_2D_H__
+#define __BLI_VORONOI_2D_H__
struct ListBase;
-/** \file BLI_voronoi.h
+/** \file BLI_voronoi_2d.h
* \ingroup bli
*/
@@ -67,4 +67,4 @@ void BLI_voronoi_triangulate(const VoronoiSite *sites, int sites_total, struct L
VoronoiTriangulationPoint **triangulated_points_r, int *triangulated_points_total_r,
int (**triangles_r)[3], int *triangles_total_r);
-#endif /* __BLI_VORONOI_H__ */
+#endif /* __BLI_VORONOI_2D_H__ */
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 9e7b4ed8b6f..5bcf4303a84 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -41,10 +41,11 @@ set(INC_SYS
set(SRC
intern/BLI_args.c
intern/BLI_array.c
- intern/BLI_dial.c
+ intern/BLI_dial_2d.c
intern/BLI_dynstr.c
intern/BLI_filelist.c
intern/BLI_ghash.c
+ intern/BLI_ghash_utils.c
intern/BLI_heap.c
intern/BLI_kdopbvh.c
intern/BLI_kdtree.c
@@ -58,10 +59,10 @@ set(SRC
intern/array_utils.c
intern/astar.c
intern/bitmap_draw_2d.c
- intern/boxpack2d.c
+ intern/boxpack_2d.c
intern/buffer.c
intern/callbacks.c
- intern/convexhull2d.c
+ intern/convexhull_2d.c
intern/dynlib.c
intern/easing.c
intern/edgehash.c
@@ -73,8 +74,8 @@ set(SRC
intern/gsqueue.c
intern/hash_md5.c
intern/hash_mm2a.c
- intern/jitter.c
- intern/lasso.c
+ intern/jitter_2d.c
+ intern/lasso_2d.c
intern/list_sort_impl.h
intern/listbase.c
intern/math_base.c
@@ -95,8 +96,8 @@ set(SRC
intern/memory_utils.c
intern/noise.c
intern/path_util.c
- intern/polyfill2d.c
- intern/polyfill2d_beautify.c
+ intern/polyfill_2d.c
+ intern/polyfill_2d_beautify.c
intern/quadric.c
intern/rand.c
intern/rct.c
@@ -117,7 +118,7 @@ set(SRC
intern/time.c
intern/timecode.c
intern/uvproject.c
- intern/voronoi.c
+ intern/voronoi_2d.c
intern/voxel.c
intern/winstuff.c
intern/winstuff_dir.c
@@ -132,14 +133,15 @@ set(SRC
BLI_bitmap.h
BLI_bitmap_draw_2d.h
BLI_blenlib.h
- BLI_boxpack2d.h
+ BLI_boxpack_2d.h
BLI_buffer.h
BLI_callbacks.h
BLI_compiler_attrs.h
BLI_compiler_compat.h
BLI_compiler_typecheck.h
- BLI_convexhull2d.h
- BLI_dial.h
+ BLI_console.h
+ BLI_convexhull_2d.h
+ BLI_dial_2d.h
BLI_dlrbTree.h
BLI_dynlib.h
BLI_dynstr.h
@@ -158,10 +160,10 @@ set(SRC
BLI_hash_mm2a.h
BLI_heap.h
BLI_iterator.h
- BLI_jitter.h
+ BLI_jitter_2d.h
BLI_kdopbvh.h
BLI_kdtree.h
- BLI_lasso.h
+ BLI_lasso_2d.h
BLI_link_utils.h
BLI_linklist.h
BLI_linklist_stack.h
@@ -185,8 +187,8 @@ set(SRC
BLI_mempool.h
BLI_noise.h
BLI_path_util.h
- BLI_polyfill2d.h
- BLI_polyfill2d_beautify.h
+ BLI_polyfill_2d.h
+ BLI_polyfill_2d_beautify.h
BLI_quadric.h
BLI_rand.h
BLI_rect.h
@@ -211,7 +213,7 @@ set(SRC
BLI_utildefines_variadic.h
BLI_uvproject.h
BLI_vfontdata.h
- BLI_voronoi.h
+ BLI_voronoi_2d.h
BLI_voxel.h
BLI_winstuff.h
PIL_time.h
diff --git a/source/blender/blenlib/intern/BLI_array.c b/source/blender/blenlib/intern/BLI_array.c
index f681d222e69..d16dd36763d 100644
--- a/source/blender/blenlib/intern/BLI_array.c
+++ b/source/blender/blenlib/intern/BLI_array.c
@@ -66,21 +66,23 @@
/**
* This function is only to be called via macros.
*
- * \note The caller must adjust \a arr_count
+ * \note The caller must adjust \a arr_len
*/
-void _bli_array_grow_func(void **arr_p, const void *arr_static,
- const int sizeof_arr_p, const int arr_count, const int num,
- const char *alloc_str)
+void _bli_array_grow_func(
+ void **arr_p, const void *arr_static,
+ const int sizeof_arr_p, const int arr_len, const int num,
+ const char *alloc_str)
{
void *arr = *arr_p;
void *arr_tmp;
- arr_tmp = MEM_mallocN(sizeof_arr_p *
- ((num < arr_count) ?
- (arr_count * 2 + 2) : (arr_count + num)), alloc_str);
+ arr_tmp = MEM_mallocN(
+ sizeof_arr_p *
+ ((num < arr_len) ?
+ (arr_len * 2 + 2) : (arr_len + num)), alloc_str);
if (arr) {
- memcpy(arr_tmp, arr, sizeof_arr_p * arr_count);
+ memcpy(arr_tmp, arr, sizeof_arr_p * arr_len);
if (arr != arr_static) {
MEM_freeN(arr);
@@ -91,6 +93,6 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
/* caller must do */
#if 0
- arr_count += num;
+ arr_len += num;
#endif
}
diff --git a/source/blender/blenlib/intern/BLI_dial.c b/source/blender/blenlib/intern/BLI_dial_2d.c
index 89f18fa10b4..d31367c5e87 100644
--- a/source/blender/blenlib/intern/BLI_dial.c
+++ b/source/blender/blenlib/intern/BLI_dial_2d.c
@@ -18,7 +18,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#include "BLI_dial.h"
+/** \file blender/blenlib/intern/BLI_dial_2d.c
+ * \ingroup bli
+ */
+
+#include "BLI_dial_2d.h"
#include "BLI_math.h"
#include "MEM_guardedalloc.h"
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index bf2f25fae69..ec75c140159 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -43,11 +43,12 @@
#include "BLI_sys_types.h" /* for intptr_t support */
#include "BLI_utildefines.h"
-#include "BLI_hash_mm2a.h"
#include "BLI_mempool.h"
#define GHASH_INTERNAL_API
-#include "BLI_ghash.h"
+#include "BLI_ghash.h" /* own include */
+
+/* keep last */
#include "BLI_strict_flags.h"
/* -------------------------------------------------------------------- */
@@ -741,7 +742,7 @@ void BLI_ghash_reserve(GHash *gh, const uint nentries_reserve)
/**
* \return size of the GHash.
*/
-uint BLI_ghash_size(GHash *gh)
+uint BLI_ghash_len(GHash *gh)
{
return gh->nentries;
}
@@ -1010,7 +1011,7 @@ void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfree
*/
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
{
- BLI_assert((int)gh->nentries == BLI_mempool_count(gh->entrypool));
+ BLI_assert((int)gh->nentries == BLI_mempool_len(gh->entrypool));
if (keyfreefp || valfreefp)
ghash_free_cb(gh, keyfreefp, valfreefp);
@@ -1044,7 +1045,7 @@ void BLI_ghash_flag_clear(GHash *gh, uint flag)
/**
* Create a new GHashIterator. The hash table must not be mutated
* while the iterator is in use, and the iterator will step exactly
- * BLI_ghash_size(gh) times before becoming done.
+ * BLI_ghash_len(gh) times before becoming done.
*
* \param gh The GHash to iterate over.
* \return Pointer to a new DynStr.
@@ -1059,7 +1060,7 @@ GHashIterator *BLI_ghashIterator_new(GHash *gh)
/**
* Init an already allocated GHashIterator. The hash table must not
* be mutated while the iterator is in use, and the iterator will
- * step exactly BLI_ghash_size(gh) times before becoming done.
+ * step exactly BLI_ghash_len(gh) times before becoming done.
*
* \param ghi The GHashIterator to initialize.
* \param gh The GHash to iterate over.
@@ -1161,219 +1162,6 @@ bool BLI_ghashIterator_done(GHashIterator *ghi)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Generic Key Hash & Comparison Functions
- * \{ */
-
-/***/
-
-#if 0
-/* works but slower */
-uint BLI_ghashutil_ptrhash(const void *key)
-{
- return (uint)(intptr_t)key;
-}
-#else
-/* based python3.3's pointer hashing function */
-uint BLI_ghashutil_ptrhash(const void *key)
-{
- size_t y = (size_t)key;
- /* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid
- * excessive hash collisions for dicts and sets */
- y = (y >> 4) | (y << (8 * sizeof(void *) - 4));
- return (uint)y;
-}
-#endif
-bool BLI_ghashutil_ptrcmp(const void *a, const void *b)
-{
- return (a != b);
-}
-
-uint BLI_ghashutil_uinthash_v4(const uint key[4])
-{
- uint hash;
- hash = key[0];
- hash *= 37;
- hash += key[1];
- hash *= 37;
- hash += key[2];
- hash *= 37;
- hash += key[3];
- return hash;
-}
-uint BLI_ghashutil_uinthash_v4_murmur(const uint key[4])
-{
- return BLI_hash_mm2((const unsigned char *)key, sizeof(int) * 4 /* sizeof(key) */, 0);
-}
-
-bool BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b)
-{
- return (memcmp(a, b, sizeof(uint[4])) != 0);
-}
-
-uint BLI_ghashutil_uinthash(uint key)
-{
- key += ~(key << 16);
- key ^= (key >> 5);
- key += (key << 3);
- key ^= (key >> 13);
- key += ~(key << 9);
- key ^= (key >> 17);
-
- return key;
-}
-
-uint BLI_ghashutil_inthash_p(const void *ptr)
-{
- uintptr_t key = (uintptr_t)ptr;
-
- key += ~(key << 16);
- key ^= (key >> 5);
- key += (key << 3);
- key ^= (key >> 13);
- key += ~(key << 9);
- key ^= (key >> 17);
-
- return (uint)(key & 0xffffffff);
-}
-
-uint BLI_ghashutil_inthash_p_murmur(const void *ptr)
-{
- uintptr_t key = (uintptr_t)ptr;
-
- return BLI_hash_mm2((const unsigned char *)&key, sizeof(key), 0);
-}
-
-uint BLI_ghashutil_inthash_p_simple(const void *ptr)
-{
- return GET_UINT_FROM_POINTER(ptr);
-}
-
-bool BLI_ghashutil_intcmp(const void *a, const void *b)
-{
- return (a != b);
-}
-
-size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b)
-{
- return hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2));
-}
-
-/**
- * This function implements the widely used "djb" hash apparently posted
- * by Daniel Bernstein to comp.lang.c some time ago. The 32 bit
- * unsigned hash value starts at 5381 and for each byte 'c' in the
- * string, is updated: ``hash = hash * 33 + c``. This
- * function uses the signed value of each byte.
- *
- * note: this is the same hash method that glib 2.34.0 uses.
- */
-uint BLI_ghashutil_strhash_n(const char *key, size_t n)
-{
- const signed char *p;
- uint h = 5381;
-
- for (p = (const signed char *)key; n-- && *p != '\0'; p++) {
- h = (uint)((h << 5) + h) + (uint)*p;
- }
-
- return h;
-}
-uint BLI_ghashutil_strhash_p(const void *ptr)
-{
- const signed char *p;
- uint h = 5381;
-
- for (p = ptr; *p != '\0'; p++) {
- h = (uint)((h << 5) + h) + (uint)*p;
- }
-
- return h;
-}
-uint BLI_ghashutil_strhash_p_murmur(const void *ptr)
-{
- const unsigned char *key = ptr;
-
- return BLI_hash_mm2(key, strlen((const char *)key) + 1, 0);
-}
-bool BLI_ghashutil_strcmp(const void *a, const void *b)
-{
- return (a == b) ? false : !STREQ(a, b);
-}
-
-GHashPair *BLI_ghashutil_pairalloc(const void *first, const void *second)
-{
- GHashPair *pair = MEM_mallocN(sizeof(GHashPair), "GHashPair");
- pair->first = first;
- pair->second = second;
- return pair;
-}
-
-uint BLI_ghashutil_pairhash(const void *ptr)
-{
- const GHashPair *pair = ptr;
- uint hash = BLI_ghashutil_ptrhash(pair->first);
- return hash ^ BLI_ghashutil_ptrhash(pair->second);
-}
-
-bool BLI_ghashutil_paircmp(const void *a, const void *b)
-{
- const GHashPair *A = a;
- const GHashPair *B = b;
-
- return (BLI_ghashutil_ptrcmp(A->first, B->first) ||
- BLI_ghashutil_ptrcmp(A->second, B->second));
-}
-
-void BLI_ghashutil_pairfree(void *ptr)
-{
- MEM_freeN(ptr);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Convenience GHash Creation Functions
- * \{ */
-
-GHash *BLI_ghash_ptr_new_ex(const char *info, const uint nentries_reserve)
-{
- return BLI_ghash_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, nentries_reserve);
-}
-GHash *BLI_ghash_ptr_new(const char *info)
-{
- return BLI_ghash_ptr_new_ex(info, 0);
-}
-
-GHash *BLI_ghash_str_new_ex(const char *info, const uint nentries_reserve)
-{
- return BLI_ghash_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info, nentries_reserve);
-}
-GHash *BLI_ghash_str_new(const char *info)
-{
- return BLI_ghash_str_new_ex(info, 0);
-}
-
-GHash *BLI_ghash_int_new_ex(const char *info, const uint nentries_reserve)
-{
- return BLI_ghash_new_ex(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, info, nentries_reserve);
-}
-GHash *BLI_ghash_int_new(const char *info)
-{
- return BLI_ghash_int_new_ex(info, 0);
-}
-
-GHash *BLI_ghash_pair_new_ex(const char *info, const uint nentries_reserve)
-{
- return BLI_ghash_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, nentries_reserve);
-}
-GHash *BLI_ghash_pair_new(const char *info)
-{
- return BLI_ghash_pair_new_ex(info, 0);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name GSet Public API
*
* Use ghash API to give 'set' functionality
@@ -1398,7 +1186,7 @@ GSet *BLI_gset_copy(GSet *gs, GHashKeyCopyFP keycopyfp)
return (GSet *)ghash_copy((GHash *)gs, keycopyfp, NULL);
}
-uint BLI_gset_size(GSet *gs)
+uint BLI_gset_len(GSet *gs)
{
return ((GHash *)gs)->nentries;
}
@@ -1557,7 +1345,7 @@ void *BLI_gset_lookup(GSet *gs, const void *key)
/**
* Returns the pointer to the key if it's found, removing it from the GSet.
- * \node Caller must handle freeing.
+ * \note Caller must handle freeing.
*/
void *BLI_gset_pop_key(GSet *gs, const void *key)
{
@@ -1577,39 +1365,6 @@ void *BLI_gset_pop_key(GSet *gs, const void *key)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Convenience GSet Creation Functions
- * \{ */
-
-GSet *BLI_gset_ptr_new_ex(const char *info, const uint nentries_reserve)
-{
- return BLI_gset_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, nentries_reserve);
-}
-GSet *BLI_gset_ptr_new(const char *info)
-{
- return BLI_gset_ptr_new_ex(info, 0);
-}
-
-GSet *BLI_gset_str_new_ex(const char *info, const uint nentries_reserve)
-{
- return BLI_gset_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info, nentries_reserve);
-}
-GSet *BLI_gset_str_new(const char *info)
-{
- return BLI_gset_str_new_ex(info, 0);
-}
-
-GSet *BLI_gset_pair_new_ex(const char *info, const uint nentries_reserve)
-{
- return BLI_gset_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, nentries_reserve);
-}
-GSet *BLI_gset_pair_new(const char *info)
-{
- return BLI_gset_pair_new_ex(info, 0);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Debugging & Introspection
* \{ */
@@ -1618,13 +1373,13 @@ GSet *BLI_gset_pair_new(const char *info)
/**
* \return number of buckets in the GHash.
*/
-int BLI_ghash_buckets_size(GHash *gh)
+int BLI_ghash_buckets_len(GHash *gh)
{
return (int)gh->nbuckets;
}
-int BLI_gset_buckets_size(GSet *gs)
+int BLI_gset_buckets_len(GSet *gs)
{
- return BLI_ghash_buckets_size((GHash *)gs);
+ return BLI_ghash_buckets_len((GHash *)gs);
}
/**
diff --git a/source/blender/blenlib/intern/BLI_ghash_utils.c b/source/blender/blenlib/intern/BLI_ghash_utils.c
new file mode 100644
index 00000000000..6554ee7c92f
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_ghash_utils.c
@@ -0,0 +1,288 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenlib/intern/BLI_ghash_utils.c
+ * \ingroup bli
+ *
+ * Helper functions and implementations of standard data types for #GHash
+ * (not it's implementation).
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_hash_mm2a.h"
+#include "BLI_ghash.h" /* own include */
+
+/* keep last */
+#include "BLI_strict_flags.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Generic Key Hash & Comparison Functions
+ * \{ */
+
+#if 0
+/* works but slower */
+uint BLI_ghashutil_ptrhash(const void *key)
+{
+ return (uint)(intptr_t)key;
+}
+#else
+/* based python3.3's pointer hashing function */
+uint BLI_ghashutil_ptrhash(const void *key)
+{
+ size_t y = (size_t)key;
+ /* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid
+ * excessive hash collisions for dicts and sets */
+ y = (y >> 4) | (y << (8 * sizeof(void *) - 4));
+ return (uint)y;
+}
+#endif
+bool BLI_ghashutil_ptrcmp(const void *a, const void *b)
+{
+ return (a != b);
+}
+
+uint BLI_ghashutil_uinthash_v4(const uint key[4])
+{
+ uint hash;
+ hash = key[0];
+ hash *= 37;
+ hash += key[1];
+ hash *= 37;
+ hash += key[2];
+ hash *= 37;
+ hash += key[3];
+ return hash;
+}
+uint BLI_ghashutil_uinthash_v4_murmur(const uint key[4])
+{
+ return BLI_hash_mm2((const unsigned char *)key, sizeof(int) * 4 /* sizeof(key) */, 0);
+}
+
+bool BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b)
+{
+ return (memcmp(a, b, sizeof(uint[4])) != 0);
+}
+
+uint BLI_ghashutil_uinthash(uint key)
+{
+ key += ~(key << 16);
+ key ^= (key >> 5);
+ key += (key << 3);
+ key ^= (key >> 13);
+ key += ~(key << 9);
+ key ^= (key >> 17);
+
+ return key;
+}
+
+uint BLI_ghashutil_inthash_p(const void *ptr)
+{
+ uintptr_t key = (uintptr_t)ptr;
+
+ key += ~(key << 16);
+ key ^= (key >> 5);
+ key += (key << 3);
+ key ^= (key >> 13);
+ key += ~(key << 9);
+ key ^= (key >> 17);
+
+ return (uint)(key & 0xffffffff);
+}
+
+uint BLI_ghashutil_inthash_p_murmur(const void *ptr)
+{
+ uintptr_t key = (uintptr_t)ptr;
+
+ return BLI_hash_mm2((const unsigned char *)&key, sizeof(key), 0);
+}
+
+uint BLI_ghashutil_inthash_p_simple(const void *ptr)
+{
+ return GET_UINT_FROM_POINTER(ptr);
+}
+
+bool BLI_ghashutil_intcmp(const void *a, const void *b)
+{
+ return (a != b);
+}
+
+size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b)
+{
+ return hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2));
+}
+
+/**
+ * This function implements the widely used "djb" hash apparently posted
+ * by Daniel Bernstein to comp.lang.c some time ago. The 32 bit
+ * unsigned hash value starts at 5381 and for each byte 'c' in the
+ * string, is updated: ``hash = hash * 33 + c``. This
+ * function uses the signed value of each byte.
+ *
+ * note: this is the same hash method that glib 2.34.0 uses.
+ */
+uint BLI_ghashutil_strhash_n(const char *key, size_t n)
+{
+ const signed char *p;
+ uint h = 5381;
+
+ for (p = (const signed char *)key; n-- && *p != '\0'; p++) {
+ h = (uint)((h << 5) + h) + (uint)*p;
+ }
+
+ return h;
+}
+uint BLI_ghashutil_strhash_p(const void *ptr)
+{
+ const signed char *p;
+ uint h = 5381;
+
+ for (p = ptr; *p != '\0'; p++) {
+ h = (uint)((h << 5) + h) + (uint)*p;
+ }
+
+ return h;
+}
+uint BLI_ghashutil_strhash_p_murmur(const void *ptr)
+{
+ const unsigned char *key = ptr;
+
+ return BLI_hash_mm2(key, strlen((const char *)key) + 1, 0);
+}
+bool BLI_ghashutil_strcmp(const void *a, const void *b)
+{
+ return (a == b) ? false : !STREQ(a, b);
+}
+
+GHashPair *BLI_ghashutil_pairalloc(const void *first, const void *second)
+{
+ GHashPair *pair = MEM_mallocN(sizeof(GHashPair), "GHashPair");
+ pair->first = first;
+ pair->second = second;
+ return pair;
+}
+
+uint BLI_ghashutil_pairhash(const void *ptr)
+{
+ const GHashPair *pair = ptr;
+ uint hash = BLI_ghashutil_ptrhash(pair->first);
+ return hash ^ BLI_ghashutil_ptrhash(pair->second);
+}
+
+bool BLI_ghashutil_paircmp(const void *a, const void *b)
+{
+ const GHashPair *A = a;
+ const GHashPair *B = b;
+
+ return (BLI_ghashutil_ptrcmp(A->first, B->first) ||
+ BLI_ghashutil_ptrcmp(A->second, B->second));
+}
+
+void BLI_ghashutil_pairfree(void *ptr)
+{
+ MEM_freeN(ptr);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Convenience GHash Creation Functions
+ * \{ */
+
+GHash *BLI_ghash_ptr_new_ex(const char *info, const uint nentries_reserve)
+{
+ return BLI_ghash_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, nentries_reserve);
+}
+GHash *BLI_ghash_ptr_new(const char *info)
+{
+ return BLI_ghash_ptr_new_ex(info, 0);
+}
+
+GHash *BLI_ghash_str_new_ex(const char *info, const uint nentries_reserve)
+{
+ return BLI_ghash_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info, nentries_reserve);
+}
+GHash *BLI_ghash_str_new(const char *info)
+{
+ return BLI_ghash_str_new_ex(info, 0);
+}
+
+GHash *BLI_ghash_int_new_ex(const char *info, const uint nentries_reserve)
+{
+ return BLI_ghash_new_ex(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, info, nentries_reserve);
+}
+GHash *BLI_ghash_int_new(const char *info)
+{
+ return BLI_ghash_int_new_ex(info, 0);
+}
+
+GHash *BLI_ghash_pair_new_ex(const char *info, const uint nentries_reserve)
+{
+ return BLI_ghash_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, nentries_reserve);
+}
+GHash *BLI_ghash_pair_new(const char *info)
+{
+ return BLI_ghash_pair_new_ex(info, 0);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Convenience GSet Creation Functions
+ * \{ */
+
+GSet *BLI_gset_ptr_new_ex(const char *info, const uint nentries_reserve)
+{
+ return BLI_gset_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, nentries_reserve);
+}
+GSet *BLI_gset_ptr_new(const char *info)
+{
+ return BLI_gset_ptr_new_ex(info, 0);
+}
+
+GSet *BLI_gset_str_new_ex(const char *info, const uint nentries_reserve)
+{
+ return BLI_gset_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info, nentries_reserve);
+}
+GSet *BLI_gset_str_new(const char *info)
+{
+ return BLI_gset_str_new_ex(info, 0);
+}
+
+GSet *BLI_gset_pair_new_ex(const char *info, const uint nentries_reserve)
+{
+ return BLI_gset_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, nentries_reserve);
+}
+GSet *BLI_gset_pair_new(const char *info)
+{
+ return BLI_gset_pair_new_ex(info, 0);
+}
+
+/** \} */
diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c
index 7c249344541..0c71e75e40f 100644
--- a/source/blender/blenlib/intern/BLI_heap.c
+++ b/source/blender/blenlib/intern/BLI_heap.c
@@ -303,7 +303,7 @@ bool BLI_heap_is_empty(const Heap *heap)
return (heap->size == 0);
}
-uint BLI_heap_size(const Heap *heap)
+uint BLI_heap_len(const Heap *heap)
{
return heap->size;
}
@@ -320,7 +320,7 @@ HeapNode *BLI_heap_top(const Heap *heap)
/**
* Pop the top node off the heap and return it's pointer.
*/
-void *BLI_heap_popmin(Heap *heap)
+void *BLI_heap_pop_min(Heap *heap)
{
BLI_assert(heap->size != 0);
@@ -348,7 +348,7 @@ void BLI_heap_remove(Heap *heap, HeapNode *node)
i = p;
}
- BLI_heap_popmin(heap);
+ BLI_heap_pop_min(heap);
}
/**
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index 9c055a227a9..06e8ade68a2 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -856,9 +856,8 @@ static void non_recursive_bvh_div_nodes_task_cb(
else {
break;
}
-
- parent->totnode = (char)(k + 1);
}
+ parent->totnode = (char)k;
}
/**
@@ -1147,7 +1146,7 @@ void BLI_bvhtree_update_tree(BVHTree *tree)
* Number of times #BLI_bvhtree_insert has been called.
* mainly useful for asserts functions to check we added the correct number.
*/
-int BLI_bvhtree_get_size(const BVHTree *tree)
+int BLI_bvhtree_get_len(const BVHTree *tree)
{
return tree->totleaf;
}
@@ -1924,6 +1923,7 @@ void BLI_bvhtree_ray_cast_all(
BLI_bvhtree_ray_cast_all_ex(tree, co, dir, radius, hit_dist, callback, userdata, BVH_RAYCAST_DEFAULT);
}
+/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index 5b13f129ad4..3a65e6c42ca 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -474,7 +474,7 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr)
}
}
-int BLI_mempool_count(BLI_mempool *pool)
+int BLI_mempool_len(BLI_mempool *pool)
{
return (int)pool->totused;
}
diff --git a/source/blender/blenlib/intern/array_store.c b/source/blender/blenlib/intern/array_store.c
index 5b1715bbb3d..df93dad4c32 100644
--- a/source/blender/blenlib/intern/array_store.c
+++ b/source/blender/blenlib/intern/array_store.c
@@ -299,7 +299,7 @@ typedef struct BChunk {
} BChunk;
/**
- * Links to store #BChunk data in #BChunkList.chunks.
+ * Links to store #BChunk data in #BChunkList.chunk_refs.
*/
typedef struct BChunkRef {
struct BChunkRef *next, *prev;
@@ -749,6 +749,7 @@ static void bchunk_list_fill_from_array(
ASSERT_CHUNKLIST_DATA(chunk_list, data);
}
+/** \} */
/* ---------------------------------------------------------------------------
* Internal Table Lookup Functions
@@ -1013,6 +1014,10 @@ static const BChunkRef *table_lookup(
/** \} */
+/** \name Main Data De-Duplication Function
+ *
+ * \{ */
+
/**
* \param data: Data to store in the returned value.
* \param data_len_original: Length of data in bytes.
@@ -1504,6 +1509,8 @@ void BLI_array_store_clear(
BLI_mempool_clear(bs->memory.chunk);
}
+/** \} */
+
/** \name BArrayStore Statistics
* \{ */
@@ -1759,7 +1766,7 @@ bool BLI_array_store_is_valid(
goto user_finally;
}
}
- if (!(BLI_mempool_count(bs->memory.chunk_list) == (int)BLI_ghash_size(chunk_list_map))) {
+ if (!(BLI_mempool_len(bs->memory.chunk_list) == (int)BLI_ghash_len(chunk_list_map))) {
ok = false;
goto user_finally;
}
@@ -1772,11 +1779,11 @@ bool BLI_array_store_is_valid(
totrefs += 1;
}
}
- if (!(BLI_mempool_count(bs->memory.chunk) == (int)BLI_ghash_size(chunk_map))) {
+ if (!(BLI_mempool_len(bs->memory.chunk) == (int)BLI_ghash_len(chunk_map))) {
ok = false;
goto user_finally;
}
- if (!(BLI_mempool_count(bs->memory.chunk_ref) == totrefs)) {
+ if (!(BLI_mempool_len(bs->memory.chunk_ref) == totrefs)) {
ok = false;
goto user_finally;
}
diff --git a/source/blender/blenlib/intern/array_utils.c b/source/blender/blenlib/intern/array_utils.c
index 32f0111babd..7b2d35a763c 100644
--- a/source/blender/blenlib/intern/array_utils.c
+++ b/source/blender/blenlib/intern/array_utils.c
@@ -308,3 +308,20 @@ bool _bli_array_iter_span(
return false;
}
+
+/**
+ * Simple utility to check memory is zeroed.
+ */
+bool _bli_array_is_zeroed(
+ const void *arr_v,
+ unsigned int arr_len, size_t arr_stride)
+{
+ const char *arr_step = (const char *)arr_v;
+ size_t i = arr_stride * arr_len;
+ while (i--) {
+ if (*(arr_step++)) {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/source/blender/blenlib/intern/astar.c b/source/blender/blenlib/intern/astar.c
index 0020dbe4612..1b57dc5a683 100644
--- a/source/blender/blenlib/intern/astar.c
+++ b/source/blender/blenlib/intern/astar.c
@@ -231,7 +231,7 @@ bool BLI_astar_graph_solve(
SET_INT_IN_POINTER(node_index_src));
while (!BLI_heap_is_empty(todo_nodes)) {
- const int node_curr_idx = GET_INT_FROM_POINTER(BLI_heap_popmin(todo_nodes));
+ const int node_curr_idx = GET_INT_FROM_POINTER(BLI_heap_pop_min(todo_nodes));
BLI_AStarGNode *node_curr = &as_graph->nodes[node_curr_idx];
LinkData *ld;
diff --git a/source/blender/blenlib/intern/boxpack2d.c b/source/blender/blenlib/intern/boxpack_2d.c
index ff17d2ac28b..cf9e29209fb 100644
--- a/source/blender/blenlib/intern/boxpack2d.c
+++ b/source/blender/blenlib/intern/boxpack_2d.c
@@ -20,7 +20,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/blenlib/intern/boxpack2d.c
+/** \file blender/blenlib/intern/boxpack_2d.c
* \ingroup bli
*/
@@ -30,7 +30,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
-#include "BLI_boxpack2d.h" /* own include */
+#include "BLI_boxpack_2d.h" /* own include */
#include "BLI_sort.h" /* qsort_r */
#define qsort_r BLI_qsort_r
diff --git a/source/blender/blenlib/intern/convexhull2d.c b/source/blender/blenlib/intern/convexhull_2d.c
index 1f1f214ce32..38928dbbaa0 100644
--- a/source/blender/blenlib/intern/convexhull2d.c
+++ b/source/blender/blenlib/intern/convexhull_2d.c
@@ -18,7 +18,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/blenlib/intern/convexhull2d.c
+/** \file blender/blenlib/intern/convexhull_2d.c
* \ingroup bli
*/
@@ -28,7 +28,7 @@
#include "MEM_guardedalloc.h"
-#include "BLI_convexhull2d.h"
+#include "BLI_convexhull_2d.h"
#include "BLI_math.h"
#include "BLI_strict_flags.h"
#include "BLI_utildefines.h"
diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c
index 772c8bd6247..7074a776aaf 100644
--- a/source/blender/blenlib/intern/edgehash.c
+++ b/source/blender/blenlib/intern/edgehash.c
@@ -527,7 +527,7 @@ bool BLI_edgehash_haskey(EdgeHash *eh, uint v0, uint v1)
/**
* Return number of keys in hash.
*/
-int BLI_edgehash_size(EdgeHash *eh)
+int BLI_edgehash_len(EdgeHash *eh)
{
return (int)eh->nentries;
}
@@ -565,7 +565,7 @@ void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp)
void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp)
{
- BLI_assert((int)eh->nentries == BLI_mempool_count(eh->epool));
+ BLI_assert((int)eh->nentries == BLI_mempool_len(eh->epool));
if (valfreefp)
edgehash_free_cb(eh, valfreefp);
@@ -599,7 +599,7 @@ void BLI_edgehash_flag_clear(EdgeHash *eh, uint flag)
/**
* Create a new EdgeHashIterator. The hash table must not be mutated
* while the iterator is in use, and the iterator will step exactly
- * BLI_edgehash_size(eh) times before becoming done.
+ * BLI_edgehash_len(eh) times before becoming done.
*/
EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh)
{
@@ -611,7 +611,7 @@ EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh)
/**
* Init an already allocated EdgeHashIterator. The hash table must not
* be mutated while the iterator is in use, and the iterator will
- * step exactly BLI_edgehash_size(eh) times before becoming done.
+ * step exactly BLI_edgehash_len(eh) times before becoming done.
*
* \param ehi The EdgeHashIterator to initialize.
* \param eh The EdgeHash to iterate over.
@@ -729,7 +729,7 @@ EdgeSet *BLI_edgeset_new(const char *info)
return BLI_edgeset_new_ex(info, 0);
}
-int BLI_edgeset_size(EdgeSet *es)
+int BLI_edgeset_len(EdgeSet *es)
{
return (int)((EdgeHash *)es)->nentries;
}
diff --git a/source/blender/blenlib/intern/gsqueue.c b/source/blender/blenlib/intern/gsqueue.c
index 25da7701924..5c8c43ab92a 100644
--- a/source/blender/blenlib/intern/gsqueue.c
+++ b/source/blender/blenlib/intern/gsqueue.c
@@ -81,7 +81,7 @@ bool BLI_gsqueue_is_empty(GSQueue *gq)
/**
* Query number elements in the queue
*/
-int BLI_gsqueue_size(GSQueue *gq)
+int BLI_gsqueue_len(GSQueue *gq)
{
GSQueueElem *elem;
int size = 0;
@@ -162,7 +162,7 @@ void BLI_gsqueue_push(GSQueue *gq, const void *item)
* \param item A pointer to an appropriately
* sized structure (the size passed to BLI_gsqueue_new).
*/
-void BLI_gsqueue_pushback(GSQueue *gq, const void *item)
+void BLI_gsqueue_push_back(GSQueue *gq, const void *item)
{
GSQueueElem *elem = MEM_mallocN(sizeof(*elem) + gq->elem_size, "gqueue_push");
memcpy(elem->data, item, gq->elem_size);
diff --git a/source/blender/blenlib/intern/jitter.c b/source/blender/blenlib/intern/jitter_2d.c
index bc2b5677fa5..26351f52c7f 100644
--- a/source/blender/blenlib/intern/jitter.c
+++ b/source/blender/blenlib/intern/jitter_2d.c
@@ -25,7 +25,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/blenlib/intern/jitter.c
+/** \file blender/blenlib/intern/jitter_2d.c
* \ingroup bli
* \brief Jitter offset table
*/
@@ -35,7 +35,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_rand.h"
-#include "BLI_jitter.h"
+#include "BLI_jitter_2d.h"
#include "BLI_strict_flags.h"
diff --git a/source/blender/blenlib/intern/lasso.c b/source/blender/blenlib/intern/lasso_2d.c
index 710da09521a..663f3ffea22 100644
--- a/source/blender/blenlib/intern/lasso.c
+++ b/source/blender/blenlib/intern/lasso_2d.c
@@ -26,7 +26,7 @@
*
*/
-/** \file blender/blenlib/intern/lasso.c
+/** \file blender/blenlib/intern/lasso_2d.c
* \ingroup bli
*/
@@ -35,7 +35,7 @@
#include "BLI_math.h"
#include "BLI_strict_flags.h"
-#include "BLI_lasso.h" /* own include */
+#include "BLI_lasso_2d.h" /* own include */
void BLI_lasso_boundbox(rcti *rect, const int mcords[][2], const unsigned int moves)
{
diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c
index 96c3972d802..b87fed571b7 100644
--- a/source/blender/blenlib/intern/listbase.c
+++ b/source/blender/blenlib/intern/listbase.c
@@ -484,7 +484,7 @@ void BLI_freelistN(ListBase *listbase)
*
* \note Use to avoid redundant looping.
*/
-int BLI_listbase_count_ex(const ListBase *listbase, const int count_max)
+int BLI_listbase_count_at_most(const ListBase *listbase, const int count_max)
{
Link *link;
int count = 0;
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index 2f5b0f420b1..4bedcbdf5bf 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -324,6 +324,27 @@ MINLINE size_t max_zz(size_t a, size_t b)
return (b < a) ? a : b;
}
+MINLINE int clamp_i(int value, int min, int max)
+{
+ return min_ii(max_ii(value, min), max);
+}
+
+MINLINE float clamp_f(float value, float min, float max)
+{
+ if (value > max) {
+ return max;
+ }
+ else if (value < min) {
+ return min;
+ }
+ return value;
+}
+
+MINLINE size_t clamp_z(size_t value, size_t min, size_t max)
+{
+ return min_zz(max_zz(value, min), max);
+}
+
/**
* Almost-equal for IEEE floats, using absolute difference method.
*
@@ -347,10 +368,8 @@ MINLINE int compare_ff_relative(float a, float b, const float max_diff, const in
{
union {float f; int i;} ua, ub;
-#if 0 /* No BLI_assert in INLINE :/ */
BLI_assert(sizeof(float) == sizeof(int));
BLI_assert(max_ulps < (1 << 22));
-#endif
if (fabsf(a - b) <= max_diff) {
return 1;
@@ -454,7 +473,7 @@ MALWAYS_INLINE __m128 _bli_math_fastpow24(const __m128 arg)
*/
/* 0x3F4CCCCD = 4/5 */
/* 0x4F55A7FB = 2^(127/(4/5) - 127) * 0.994^(1/(4/5)) */
- /* error max = 0.17 avg = 0.0018 |avg| = 0.05 */
+ /* error max = 0.17, avg = 0.0018, |avg| = 0.05 */
__m128 x = _bli_math_fastpow(0x3F4CCCCD, 0x4F55A7FB, arg);
__m128 arg2 = _mm_mul_ps(arg, arg);
__m128 arg4 = _mm_mul_ps(arg2, arg2);
diff --git a/source/blender/blenlib/intern/math_bits_inline.c b/source/blender/blenlib/intern/math_bits_inline.c
index 37fdcd7878a..9b16756134e 100644
--- a/source/blender/blenlib/intern/math_bits_inline.c
+++ b/source/blender/blenlib/intern/math_bits_inline.c
@@ -34,7 +34,7 @@
MINLINE int bitscan_forward_i(int a)
{
BLI_assert(a != 0);
-# ifdef _MSC_VER
+#ifdef _MSC_VER
unsigned long ctz;
_BitScanForward(&ctz, a);
return ctz;
@@ -63,7 +63,7 @@ MINLINE unsigned int bitscan_forward_clear_uint(unsigned int *a)
MINLINE int bitscan_reverse_i(int a)
{
BLI_assert(a != 0);
-# ifdef _MSC_VER
+#ifdef _MSC_VER
unsigned long clz;
_BitScanReverse(&clz, a);
return clz;
diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c
index cb39134af45..534abeb913d 100644
--- a/source/blender/blenlib/intern/math_color.c
+++ b/source/blender/blenlib/intern/math_color.c
@@ -656,135 +656,80 @@ void rgb_to_lab(float r, float g, float b, float *ll, float *la, float *lb)
xyz_to_lab(x, y, z, ll, la, lb);
}
-static void xyz_to_lms(float x, float y, float z, float *l, float *m, float *s)
-{
- *l = 0.3897f * x + 0.6890f * y - 0.0787f * z;
- *m = -0.2298f * x + 1.1834f * y + 0.0464f * z;
- *s = z;
-}
-
-static void lms_to_xyz(float l, float m, float s, float *x, float *y, float *z)
-{
- *x = 1.9102f * l - 1.1121f * m + 0.2019f * s;
- *y = 0.3709f * l + 0.6290f * m + 0.0000f * s;
- *z = s;
-}
-
-static void normalize_rgb(float rgb[3])
-{
- const float max = max_fff(rgb[0], rgb[1], rgb[2]);
+/* ****************************** blackbody ******************************** */
- if (max > 0.0f) {
- mul_v3_fl(rgb, 1.0f / max);
- }
-}
-
-/* Color rendering of spectra, adapted from public domain code by John Walker,
- * http://www.fourmilab.ch/
+/* Calculate color in range 800..12000 using an approximation
+ * a/x+bx+c for R and G and ((at + b)t + c)t + d) for B
+ * Max absolute error for RGB is (0.00095, 0.00077, 0.00057),
+ * which is enough to get the same 8 bit/channel color.
*/
-static void spectrum_to_xyz(float temperature, float xyz[3])
-{
- int i;
- float lambda, x = 0.0f, y = 0.0f, z = 0.0f, xyz_sum;
-
- /* CIE colour matching functions xBar, yBar, and zBar for wavelengths from
- * 380 through 780 nanometers, every 5 nanometers.
- * For a wavelength lambda in this range:
- *
- * cie_colour_match[(lambda - 380) / 5][0] = xBar
- * cie_colour_match[(lambda - 380) / 5][1] = yBar
- * cie_colour_match[(lambda - 380) / 5][2] = zBar
- */
-
- const float cie_colour_match[81][3] = {
- {0.0014f, 0.0000f, 0.0065f}, {0.0022f, 0.0001f, 0.0105f}, {0.0042f, 0.0001f, 0.0201f},
- {0.0076f, 0.0002f, 0.0362f}, {0.0143f, 0.0004f, 0.0679f}, {0.0232f, 0.0006f, 0.1102f},
- {0.0435f, 0.0012f, 0.2074f}, {0.0776f, 0.0022f, 0.3713f}, {0.1344f, 0.0040f, 0.6456f},
- {0.2148f, 0.0073f, 1.0391f}, {0.2839f, 0.0116f, 1.3856f}, {0.3285f, 0.0168f, 1.6230f},
- {0.3483f, 0.0230f, 1.7471f}, {0.3481f, 0.0298f, 1.7826f}, {0.3362f, 0.0380f, 1.7721f},
- {0.3187f, 0.0480f, 1.7441f}, {0.2908f, 0.0600f, 1.6692f}, {0.2511f, 0.0739f, 1.5281f},
- {0.1954f, 0.0910f, 1.2876f}, {0.1421f, 0.1126f, 1.0419f}, {0.0956f, 0.1390f, 0.8130f},
- {0.0580f, 0.1693f, 0.6162f}, {0.0320f, 0.2080f, 0.4652f}, {0.0147f, 0.2586f, 0.3533f},
- {0.0049f, 0.3230f, 0.2720f}, {0.0024f, 0.4073f, 0.2123f}, {0.0093f, 0.5030f, 0.1582f},
- {0.0291f, 0.6082f, 0.1117f}, {0.0633f, 0.7100f, 0.0782f}, {0.1096f, 0.7932f, 0.0573f},
- {0.1655f, 0.8620f, 0.0422f}, {0.2257f, 0.9149f, 0.0298f}, {0.2904f, 0.9540f, 0.0203f},
- {0.3597f, 0.9803f, 0.0134f}, {0.4334f, 0.9950f, 0.0087f}, {0.5121f, 1.0000f, 0.0057f},
- {0.5945f, 0.9950f, 0.0039f}, {0.6784f, 0.9786f, 0.0027f}, {0.7621f, 0.9520f, 0.0021f},
- {0.8425f, 0.9154f, 0.0018f}, {0.9163f, 0.8700f, 0.0017f}, {0.9786f, 0.8163f, 0.0014f},
- {1.0263f, 0.7570f, 0.0011f}, {1.0567f, 0.6949f, 0.0010f}, {1.0622f, 0.6310f, 0.0008f},
- {1.0456f, 0.5668f, 0.0006f}, {1.0026f, 0.5030f, 0.0003f}, {0.9384f, 0.4412f, 0.0002f},
- {0.8544f, 0.3810f, 0.0002f}, {0.7514f, 0.3210f, 0.0001f}, {0.6424f, 0.2650f, 0.0000f},
- {0.5419f, 0.2170f, 0.0000f}, {0.4479f, 0.1750f, 0.0000f}, {0.3608f, 0.1382f, 0.0000f},
- {0.2835f, 0.1070f, 0.0000f}, {0.2187f, 0.0816f, 0.0000f}, {0.1649f, 0.0610f, 0.0000f},
- {0.1212f, 0.0446f, 0.0000f}, {0.0874f, 0.0320f, 0.0000f}, {0.0636f, 0.0232f, 0.0000f},
- {0.0468f, 0.0170f, 0.0000f}, {0.0329f, 0.0119f, 0.0000f}, {0.0227f, 0.0082f, 0.0000f},
- {0.0158f, 0.0057f, 0.0000f}, {0.0114f, 0.0041f, 0.0000f}, {0.0081f, 0.0029f, 0.0000f},
- {0.0058f, 0.0021f, 0.0000f}, {0.0041f, 0.0015f, 0.0000f}, {0.0029f, 0.0010f, 0.0000f},
- {0.0020f, 0.0007f, 0.0000f}, {0.0014f, 0.0005f, 0.0000f}, {0.0010f, 0.0004f, 0.0000f},
- {0.0007f, 0.0002f, 0.0000f}, {0.0005f, 0.0002f, 0.0000f}, {0.0003f, 0.0001f, 0.0000f},
- {0.0002f, 0.0001f, 0.0000f}, {0.0002f, 0.0001f, 0.0000f}, {0.0001f, 0.0000f, 0.0000f},
- {0.0001f, 0.0000f, 0.0000f}, {0.0001f, 0.0000f, 0.0000f}, {0.0000f, 0.0000f, 0.0000f}
- };
-
- for (i = 0, lambda = 380.0f; lambda < 780.1f; i++, lambda += 5.0f) {
- /* wavelength in meter */
- const float wlm = lambda * 1e-9f;
- const float Me = (3.74183e-16f * powf(wlm, -5.0f)) / (expf(1.4388e-2f / (wlm * temperature)) - 1.0f);
-
- x += Me * cie_colour_match[i][0];
- y += Me * cie_colour_match[i][1];
- z += Me * cie_colour_match[i][2];
+static const float blackbody_table_r[6][3] = {
+ { 2.52432244e+03f, -1.06185848e-03f, 3.11067539e+00f },
+ { 3.37763626e+03f, -4.34581697e-04f, 1.64843306e+00f },
+ { 4.10671449e+03f, -8.61949938e-05f, 6.41423749e-01f },
+ { 4.66849800e+03f, 2.85655028e-05f, 1.29075375e-01f },
+ { 4.60124770e+03f, 2.89727618e-05f, 1.48001316e-01f },
+ { 3.78765709e+03f, 9.36026367e-06f, 3.98995841e-01f },
+};
+
+static const float blackbody_table_g[6][3] = {
+ { -7.50343014e+02f, 3.15679613e-04f, 4.73464526e-01f },
+ { -1.00402363e+03f, 1.29189794e-04f, 9.08181524e-01f },
+ { -1.22075471e+03f, 2.56245413e-05f, 1.20753416e+00f },
+ { -1.42546105e+03f, -4.01730887e-05f, 1.44002695e+00f },
+ { -1.18134453e+03f, -2.18913373e-05f, 1.30656109e+00f },
+ { -5.00279505e+02f, -4.59745390e-06f, 1.09090465e+00f },
+};
+
+static const float blackbody_table_b[6][4] = {
+ { 0.0f, 0.0f, 0.0f, 0.0f },
+ { 0.0f, 0.0f, 0.0f, 0.0f },
+ { 0.0f, 0.0f, 0.0f, 0.0f },
+ { -2.02524603e-11f, 1.79435860e-07f, -2.60561875e-04f, -1.41761141e-02f },
+ { -2.22463426e-13f, -1.55078698e-08f, 3.81675160e-04f, -7.30646033e-01f },
+ { 6.72595954e-13f, -2.73059993e-08f, 4.24068546e-04f, -7.52204323e-01f },
+};
+
+static void blackbody_temperature_to_rgb(float rgb[3], float t)
+{
+ if(t >= 12000.0f) {
+ rgb[0] = 0.826270103f;
+ rgb[1] = 0.994478524f;
+ rgb[2] = 1.56626022f;
+ }
+ else if(t < 965.0f) {
+ rgb[0] = 4.70366907f;
+ rgb[1] = 0.0f;
+ rgb[2] = 0.0f;
+ }
+ else {
+ int i = (t >= 6365.0f)? 5:
+ (t >= 3315.0f)? 4:
+ (t >= 1902.0f)? 3:
+ (t >= 1449.0f)? 2:
+ (t >= 1167.0f)? 1: 0;
+
+ const float *r = blackbody_table_r[i];
+ const float *g = blackbody_table_g[i];
+ const float *b = blackbody_table_b[i];
+
+ const float t_inv = 1.0f / t;
+ rgb[0] = r[0] * t_inv + r[1] * t + r[2];
+ rgb[1] = g[0] * t_inv + g[1] * t + g[2];
+ rgb[2] = ((b[0] * t + b[1]) * t + b[2]) * t + b[3];
}
-
- xyz_sum = (x + y + z);
-
- xyz[0] = x / xyz_sum;
- xyz[1] = y / xyz_sum;
- xyz[2] = z / xyz_sum;
}
void blackbody_temperature_to_rgb_table(float *r_table, int width, float min, float max)
{
- int i, j = 0, dj = 1;
- float rgb[3], xyz[3], lms[3], lms_w[3];
- float bb_temp;
-
- if (min < max) {
- SWAP(float, min, max);
- j = width - 1;
- dj = -1;
- }
+ for (int i = 0; i < width; i++) {
+ float temperature = min + (max - min) / (float)width * (float)i;
- for (i = 0; i < width; i++, j += dj) {
- bb_temp = min + (max - min) / (float)width * (float)i;
+ float rgb[3];
+ blackbody_temperature_to_rgb(rgb, temperature);
- /* integrate blackbody radiation spectrum to XYZ */
- spectrum_to_xyz(bb_temp, xyz);
-
- /* normalize highest temperature to white (in LMS system) */
- xyz_to_lms(xyz[0], xyz[1], xyz[2], &lms[0], &lms[1], &lms[2]);
-
- if (i == 0) {
- lms_w[0] = 1.0f / lms[0];
- lms_w[1] = 1.0f / lms[1];
- lms_w[2] = 1.0f / lms[2];
- }
-
- mul_v3_v3(lms, lms_w);
-
- lms_to_xyz(lms[0], lms[1], lms[2], &xyz[0], &xyz[1], &xyz[2]);
-
- /* convert to RGB */
- xyz_to_rgb(xyz[0], xyz[1], xyz[2], &rgb[0], &rgb[1], &rgb[2], BLI_XYZ_CIE);
- constrain_rgb(&rgb[0], &rgb[1], &rgb[2]);
- normalize_rgb(rgb);
-
- copy_v3_v3(&r_table[(j << 2)], rgb);
-
- if (rgb[2] > 0.1f)
- r_table[(j << 2) + 3] = rgb[2];
- else
- r_table[(j << 2) + 3] = 0.0f;
+ copy_v3_v3(&r_table[i * 4], rgb);
+ r_table[i * 4 + 3] = 0.0f;
}
}
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 78797e603be..171af1c8264 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -3813,7 +3813,7 @@ void orthographic_m4(float matrix[4][4], const float left, const float right, co
matrix[3][0] = -(right + left) / Xdelta;
matrix[1][1] = 2.0f / Ydelta;
matrix[3][1] = -(top + bottom) / Ydelta;
- matrix[2][2] = -2.0f / Zdelta; /* note: negate Z */
+ matrix[2][2] = -2.0f / Zdelta; /* note: negate Z */
matrix[3][2] = -(farClip + nearClip) / Zdelta;
}
@@ -3832,7 +3832,7 @@ void perspective_m4(float mat[4][4], const float left, const float right, const
}
mat[0][0] = nearClip * 2.0f / Xdelta;
mat[1][1] = nearClip * 2.0f / Ydelta;
- mat[2][0] = (right + left) / Xdelta; /* note: negate Z */
+ mat[2][0] = (right + left) / Xdelta; /* note: negate Z */
mat[2][1] = (top + bottom) / Ydelta;
mat[2][2] = -(farClip + nearClip) / Zdelta;
mat[2][3] = -1.0f;
@@ -4968,6 +4968,18 @@ int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], con
return ret;
}
+bool is_quad_flip_v3_first_third_fast(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
+{
+ float d_12[3], d_13[3], d_14[3];
+ float cross_a[3], cross_b[3];
+ sub_v3_v3v3(d_12, v2, v1);
+ sub_v3_v3v3(d_13, v3, v1);
+ sub_v3_v3v3(d_14, v4, v1);
+ cross_v3_v3v3(cross_a, d_12, d_13);
+ cross_v3_v3v3(cross_b, d_14, d_13);
+ return dot_v3v3(cross_a, cross_b) > 0.0f;
+}
+
/**
* Return the value which the distance between points will need to be scaled by,
* to define a handle, given both points are on a perfect circle.
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index 05562502278..d6e48fa59e7 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -890,6 +890,8 @@ void rotate_normalized_v3_v3v3fl(float out[3], const float p[3], const float axi
void rotate_v3_v3v3fl(float r[3], const float p[3], const float axis[3], const float angle)
{
+ BLI_assert(r != p);
+
float axis_n[3];
normalize_v3_v3(axis_n, axis);
diff --git a/source/blender/blenlib/intern/polyfill2d.c b/source/blender/blenlib/intern/polyfill_2d.c
index 018e2f9be5a..8c0870f0c07 100644
--- a/source/blender/blenlib/intern/polyfill2d.c
+++ b/source/blender/blenlib/intern/polyfill_2d.c
@@ -18,7 +18,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/blenlib/intern/polyfill2d.c
+/** \file blender/blenlib/intern/polyfill_2d.c
* \ingroup bli
*
* An ear clipping algorithm to triangulate single boundary polygons.
@@ -53,7 +53,7 @@
#include "BLI_memarena.h"
#include "BLI_alloca.h"
-#include "BLI_polyfill2d.h" /* own include */
+#include "BLI_polyfill_2d.h" /* own include */
#include "BLI_strict_flags.h"
diff --git a/source/blender/blenlib/intern/polyfill2d_beautify.c b/source/blender/blenlib/intern/polyfill_2d_beautify.c
index c0c95da5c63..17f3205aaff 100644
--- a/source/blender/blenlib/intern/polyfill2d_beautify.c
+++ b/source/blender/blenlib/intern/polyfill_2d_beautify.c
@@ -18,7 +18,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/blenlib/intern/polyfill2d_beautify.c
+/** \file blender/blenlib/intern/polyfill_2d_beautify.c
* \ingroup bli
*
* This function is to improve the tessellation resulting from polyfill2d,
@@ -44,7 +44,7 @@
#include "BLI_memarena.h"
#include "BLI_heap.h"
-#include "BLI_polyfill2d_beautify.h" /* own include */
+#include "BLI_polyfill_2d_beautify.h" /* own include */
#include "BLI_strict_flags.h"
@@ -265,7 +265,8 @@ static void polyedge_rotate(
struct HalfEdge *e)
{
/** CCW winding, rotate internal edge to new vertical state.
- * <pre>
+ *
+ * \code{.unparsed}
* Before After
* X X
* / \ /|\
@@ -276,7 +277,7 @@ static void polyedge_rotate(
* e2\ /e1 e2\ | /e1
* \ / \|/
* X X
- * </pre>
+ * \endcode
*/
struct HalfEdge *ed[6];
uint ed_index[6];
@@ -401,7 +402,7 @@ void BLI_polyfill_beautify(
}
while (BLI_heap_is_empty(eheap) == false) {
- struct HalfEdge *e = BLI_heap_popmin(eheap);
+ struct HalfEdge *e = BLI_heap_pop_min(eheap);
eheap_table[e->base_index] = NULL;
polyedge_rotate(half_edges, e);
diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c
index 1a178db1413..700524965f0 100644
--- a/source/blender/blenlib/intern/rand.c
+++ b/source/blender/blenlib/intern/rand.c
@@ -386,6 +386,8 @@ void BLI_halton_1D(unsigned int prime, double offset, int n, double *r)
{
const double invprime = 1.0 / (double)prime;
+ *r = 0.0;
+
for (int s = 0; s < n; s++) {
*r = halton_ex(invprime, &offset);
}
@@ -395,6 +397,8 @@ void BLI_halton_2D(unsigned int prime[2], double offset[2], int n, double *r)
{
const double invprimes[2] = {1.0 / (double)prime[0], 1.0 / (double)prime[1]};
+ r[0] = r[1] = 0.0;
+
for (int s = 0; s < n; s++) {
for (int i = 0; i < 2; i++) {
r[i] = halton_ex(invprimes[i], &offset[i]);
@@ -406,6 +410,8 @@ void BLI_halton_3D(unsigned int prime[3], double offset[3], int n, double *r)
{
const double invprimes[3] = {1.0 / (double)prime[0], 1.0 / (double)prime[1], 1.0 / (double)prime[2]};
+ r[0] = r[1] = r[2] = 0.0;
+
for (int s = 0; s < n; s++) {
for (int i = 0; i < 3; i++) {
r[i] = halton_ex(invprimes[i], &offset[i]);
diff --git a/source/blender/blenlib/intern/smallhash.c b/source/blender/blenlib/intern/smallhash.c
index 1b862ffe005..56d77abed24 100644
--- a/source/blender/blenlib/intern/smallhash.c
+++ b/source/blender/blenlib/intern/smallhash.c
@@ -310,7 +310,7 @@ bool BLI_smallhash_haskey(const SmallHash *sh, uintptr_t key)
return (e != NULL);
}
-int BLI_smallhash_count(const SmallHash *sh)
+int BLI_smallhash_len(const SmallHash *sh)
{
return (int)sh->nentries;
}
diff --git a/source/blender/blenlib/intern/sort_utils.c b/source/blender/blenlib/intern/sort_utils.c
index c75e8e7455f..2d55e77b98b 100644
--- a/source/blender/blenlib/intern/sort_utils.c
+++ b/source/blender/blenlib/intern/sort_utils.c
@@ -37,6 +37,10 @@ struct SortAnyByInt {
int sort_value;
};
+struct SortAnyByPtr {
+ const void *sort_value;
+};
+
int BLI_sortutil_cmp_float(const void *a_, const void *b_)
{
const struct SortAnyByFloat *a = a_;
@@ -72,3 +76,21 @@ int BLI_sortutil_cmp_int_reverse(const void *a_, const void *b_)
else if (a->sort_value > b->sort_value) return -1;
else return 0;
}
+
+int BLI_sortutil_cmp_ptr(const void *a_, const void *b_)
+{
+ const struct SortAnyByPtr *a = a_;
+ const struct SortAnyByPtr *b = b_;
+ if (a->sort_value > b->sort_value) return 1;
+ else if (a->sort_value < b->sort_value) return -1;
+ else return 0;
+}
+
+int BLI_sortutil_cmp_ptr_reverse(const void *a_, const void *b_)
+{
+ const struct SortAnyByPtr *a = a_;
+ const struct SortAnyByPtr *b = b_;
+ if (a->sort_value < b->sort_value) return 1;
+ else if (a->sort_value > b->sort_value) return -1;
+ else return 0;
+}
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index c08329ef34f..f69b35ce5a9 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -185,7 +185,7 @@ size_t BLI_file_size(const char *path)
}
/**
- * Returns the st_mode from statting the specified path name, or 0 if it couldn't be statted
+ * Returns the st_mode from stat-ing the specified path name, or 0 if stat fails
* (most likely doesn't exist or no access).
*/
int BLI_exists(const char *name)
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index 6022732025b..1a6fd082e95 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -208,7 +208,7 @@ size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src)
}
/**
- * Portable replacement for #vsnprintf
+ * Portable replacement for `vsnprintf`.
*/
size_t BLI_vsnprintf(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg)
{
@@ -503,7 +503,7 @@ int BLI_strcaseeq(const char *a, const char *b)
}
/**
- * Portable replacement for #strcasestr (not available in MSVC)
+ * Portable replacement for `strcasestr` (not available in MSVC)
*/
char *BLI_strcasestr(const char *s, const char *find)
{
@@ -931,13 +931,13 @@ size_t BLI_str_partition_ex(
if (end) {
if (from_right) {
for (tmp = end - 1; (tmp >= str) && (*tmp != *d); tmp--);
- if (tmp < str) {
+ if (tmp < str) {
tmp = NULL;
}
}
else {
tmp = func(str, *d);
- if (tmp >= end) {
+ if (tmp >= end) {
tmp = NULL;
}
}
diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c
index 05cfe4f3972..5d3c6b35ac1 100644
--- a/source/blender/blenlib/intern/task.c
+++ b/source/blender/blenlib/intern/task.c
@@ -696,7 +696,7 @@ static TaskPool *task_pool_create_ex(TaskScheduler *scheduler,
* and malloc could be non-thread safe at this point because
* no other jobs are running.
*/
- BLI_begin_threaded_malloc();
+ BLI_threaded_malloc_begin();
return pool;
}
@@ -763,7 +763,7 @@ void BLI_task_pool_free(TaskPool *pool)
MEM_freeN(pool);
- BLI_end_threaded_malloc();
+ BLI_threaded_malloc_end();
}
BLI_INLINE bool task_can_use_local_queues(TaskPool *pool, int thread_id)
@@ -1310,11 +1310,11 @@ static void parallel_mempool_func(
/**
* This function allows to parallelize for loops over Mempool items.
*
- * \param pool The iterable BLI_mempool to loop over.
- * \param userdata Common userdata passed to all instances of \a func.
- * \param func Callback function.
- * \param use_threading If \a true, actually split-execute loop in threads, else just do a sequential forloop
- * (allows caller to use any kind of test to switch on parallelization or not).
+ * \param mempool: The iterable BLI_mempool to loop over.
+ * \param userdata: Common userdata passed to all instances of \a func.
+ * \param func: Callback function.
+ * \param use_threading: If \a true, actually split-execute loop in threads, else just do a sequential for loop
+ * (allows caller to use any kind of test to switch on parallelization or not).
*
* \note There is no static scheduling here.
*/
@@ -1329,7 +1329,7 @@ void BLI_task_parallel_mempool(
ParallelMempoolState state;
int i, num_threads, num_tasks;
- if (BLI_mempool_count(mempool) == 0) {
+ if (BLI_mempool_len(mempool) == 0) {
return;
}
diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c
index 2f961701801..761f3982e28 100644
--- a/source/blender/blenlib/intern/threads.c
+++ b/source/blender/blenlib/intern/threads.c
@@ -83,13 +83,13 @@ static TaskScheduler *task_scheduler = NULL;
* int maxthreads = 2;
* int cont = 1;
*
- * BLI_init_threads(&lb, do_something_func, maxthreads);
+ * BLI_threadpool_init(&lb, do_something_func, maxthreads);
*
* while (cont) {
* if (BLI_available_threads(&lb) && !(escape loop event)) {
* // get new job (data pointer)
* // tag job 'processed
- * BLI_insert_thread(&lb, job);
+ * BLI_threadpool_insert(&lb, job);
* }
* else PIL_sleep_ms(50);
*
@@ -98,7 +98,7 @@ static TaskScheduler *task_scheduler = NULL;
* for (go over all jobs)
* if (job is ready) {
* if (job was not removed) {
- * BLI_remove_thread(&lb, job);
+ * BLI_threadpool_remove(&lb, job);
* }
* }
* else cont = 1;
@@ -110,7 +110,7 @@ static TaskScheduler *task_scheduler = NULL;
* }
* }
*
- * BLI_end_threads(&lb);
+ * BLI_threadpool_end(&lb);
*
************************************************ */
static SpinLock _malloc_lock;
@@ -183,7 +183,7 @@ TaskScheduler *BLI_task_scheduler_get(void)
* problem otherwise: scene render will kill of the mutex!
*/
-void BLI_init_threads(ListBase *threadbase, void *(*do_thread)(void *), int tot)
+void BLI_threadpool_init(ListBase *threadbase, void *(*do_thread)(void *), int tot)
{
int a;
@@ -228,7 +228,7 @@ int BLI_available_threads(ListBase *threadbase)
}
/* returns thread number, for sample patterns or threadsafe tables */
-int BLI_available_thread_index(ListBase *threadbase)
+int BLI_threadpool_available_thread_index(ListBase *threadbase)
{
ThreadSlot *tslot;
int counter = 0;
@@ -258,7 +258,7 @@ int BLI_thread_is_main(void)
return pthread_equal(pthread_self(), mainid);
}
-void BLI_insert_thread(ListBase *threadbase, void *callerdata)
+void BLI_threadpool_insert(ListBase *threadbase, void *callerdata)
{
ThreadSlot *tslot;
@@ -273,7 +273,7 @@ void BLI_insert_thread(ListBase *threadbase, void *callerdata)
printf("ERROR: could not insert thread slot\n");
}
-void BLI_remove_thread(ListBase *threadbase, void *callerdata)
+void BLI_threadpool_remove(ListBase *threadbase, void *callerdata)
{
ThreadSlot *tslot;
@@ -286,7 +286,7 @@ void BLI_remove_thread(ListBase *threadbase, void *callerdata)
}
}
-void BLI_remove_thread_index(ListBase *threadbase, int index)
+void BLI_threadpool_remove_index(ListBase *threadbase, int index)
{
ThreadSlot *tslot;
int counter = 0;
@@ -301,7 +301,7 @@ void BLI_remove_thread_index(ListBase *threadbase, int index)
}
}
-void BLI_remove_threads(ListBase *threadbase)
+void BLI_threadpool_clear(ListBase *threadbase)
{
ThreadSlot *tslot;
@@ -314,7 +314,7 @@ void BLI_remove_threads(ListBase *threadbase)
}
}
-void BLI_end_threads(ListBase *threadbase)
+void BLI_threadpool_end(ListBase *threadbase)
{
ThreadSlot *tslot;
@@ -418,12 +418,12 @@ static ThreadMutex *global_mutex_from_type(const int type)
}
}
-void BLI_lock_thread(int type)
+void BLI_thread_lock(int type)
{
pthread_mutex_lock(global_mutex_from_type(type));
}
-void BLI_unlock_thread(int type)
+void BLI_thread_unlock(int type)
{
pthread_mutex_unlock(global_mutex_from_type(type));
}
@@ -773,12 +773,12 @@ void *BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms)
return work;
}
-int BLI_thread_queue_size(ThreadQueue *queue)
+int BLI_thread_queue_len(ThreadQueue *queue)
{
int size;
pthread_mutex_lock(&queue->mutex);
- size = BLI_gsqueue_size(queue->queue);
+ size = BLI_gsqueue_len(queue->queue);
pthread_mutex_unlock(&queue->mutex);
return size;
@@ -819,7 +819,7 @@ void BLI_thread_queue_wait_finish(ThreadQueue *queue)
/* ************************************************ */
-void BLI_begin_threaded_malloc(void)
+void BLI_threaded_malloc_begin(void)
{
unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1);
if (level == 0) {
@@ -832,7 +832,7 @@ void BLI_begin_threaded_malloc(void)
}
}
-void BLI_end_threaded_malloc(void)
+void BLI_threaded_malloc_end(void)
{
unsigned int level = atomic_sub_and_fetch_u(&thread_levels, 1);
if (level == 0) {
diff --git a/source/blender/blenlib/intern/voronoi.c b/source/blender/blenlib/intern/voronoi_2d.c
index e0cbe278ffb..40e98d5914c 100644
--- a/source/blender/blenlib/intern/voronoi.c
+++ b/source/blender/blenlib/intern/voronoi_2d.c
@@ -23,20 +23,18 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/*
+/** \file blender/blenlib/intern/voronoi_2d.c
+ * \ingroup bli
+ *
* Fortune's algorithm implemented using explanation and some code snippets from
* http://blog.ivank.net/fortunes-algorithm-and-implementation.html
*/
-/** \file blender/blenlib/intern/voronoi.c
- * \ingroup bli
- */
-
#include "MEM_guardedalloc.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_voronoi.h"
+#include "BLI_voronoi_2d.h"
#include "BLI_utildefines.h"
#define VORONOI_EPS 1e-2f
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 0da15fe5bbc..7b31415ddcf 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -160,6 +160,8 @@ void BLO_update_defaults_startup_blend(struct Main *mainvar);
struct BlendThumbnail *BLO_thumbnail_from_file(const char *filepath);
+struct Main *BLO_main_from_memfile(struct MemFile *memfile, struct Main *bmain, struct Scene **r_scene);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenloader/BLO_undofile.h b/source/blender/blenloader/BLO_undofile.h
index fb96ec75e62..c407ea31b9b 100644
--- a/source/blender/blenloader/BLO_undofile.h
+++ b/source/blender/blenloader/BLO_undofile.h
@@ -33,25 +33,40 @@
* \ingroup blenloader
*/
+struct Scene;
+
typedef struct {
void *next, *prev;
-
- char *buf;
- unsigned int ident, size;
-
+ const char *buf;
+ /** Size in bytes. */
+ unsigned int size;
+ /** When true, this chunk doesn't own the memory, it's shared with a previous #MemFileChunk */
+ bool is_identical;
} MemFileChunk;
typedef struct MemFile {
ListBase chunks;
- unsigned int size;
+ size_t size;
} MemFile;
+typedef struct MemFileUndoData {
+ char filename[1024]; /* FILE_MAX */
+ MemFile memfile;
+ size_t undo_size;
+} MemFileUndoData;
+
/* actually only used writefile.c */
-extern void memfile_chunk_add(MemFile *compare, MemFile *current, const char *buf, unsigned int size);
+extern void memfile_chunk_add(
+ MemFile *memfile, const char *buf, unsigned int size,
+ MemFileChunk **compchunk_step);
/* exports */
extern void BLO_memfile_free(MemFile *memfile);
extern void BLO_memfile_merge(MemFile *first, MemFile *second);
-#endif
+/* utilities */
+extern struct Main *BLO_memfile_main_get(struct MemFile *memfile, struct Main *bmain, struct Scene **r_scene);
+extern bool BLO_memfile_write_file(struct MemFile *memfile, const char *filename);
+
+#endif /* __BLO_UNDOFILE_H__ */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 9fd1c80a66a..ac5673e1402 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -88,7 +88,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_nla_types.h"
#include "DNA_node_types.h"
-#include "DNA_object_fluidsim.h" // NT
+#include "DNA_object_fluidsim_types.h"
#include "DNA_object_types.h"
#include "DNA_packedFile_types.h"
#include "DNA_particle_types.h"
@@ -2289,6 +2289,10 @@ static void direct_link_id(FileData *fd, ID *id)
}
id->py_instance = NULL;
+ /* That way datablock reading not going through main read_libblock() function are still in a clear tag state.
+ * (glowering at certain nodetree fake datablock here...). */
+ id->tag = 0;
+
/* Link direct data of overrides. */
if (id->override_static) {
id->override_static = newdataadr(fd, id->override_static);
@@ -2906,6 +2910,7 @@ static void direct_link_workspace(FileData *fd, WorkSpace *workspace, const Main
link_list(fd, &workspace->hook_layout_relations);
link_list(fd, &workspace->scene_viewlayer_relations);
link_list(fd, BKE_workspace_transform_orientations_get(workspace));
+ link_list(fd, &workspace->owner_ids);
for (WorkSpaceDataRelation *relation = workspace->hook_layout_relations.first;
relation;
@@ -3862,15 +3867,11 @@ static void lib_link_text(FileData *fd, Main *main)
static void direct_link_text(FileData *fd, Text *text)
{
TextLine *ln;
-
+
text->name = newdataadr(fd, text->name);
-
- text->undo_pos = -1;
- text->undo_len = TXT_INIT_UNDO;
- text->undo_buf = MEM_mallocN(text->undo_len, "undo buf");
-
+
text->compiled = NULL;
-
+
#if 0
if (text->flags & TXT_ISEXT) {
BKE_text_reload(text);
@@ -4408,6 +4409,9 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
part->roughcurve = newdataadr(fd, part->roughcurve);
if (part->roughcurve)
direct_link_curvemapping(fd, part->roughcurve);
+ part->twistcurve = newdataadr(fd, part->twistcurve);
+ if (part->twistcurve)
+ direct_link_curvemapping(fd, part->twistcurve);
part->effector_weights = newdataadr(fd, part->effector_weights);
if (!part->effector_weights)
@@ -4524,7 +4528,6 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
BLI_listbase_clear(&psys->pathcachebufs);
BLI_listbase_clear(&psys->childcachebufs);
psys->pdd = NULL;
- psys->renderdata = NULL;
if (psys->clmd) {
psys->clmd = newdataadr(fd, psys->clmd);
@@ -4961,7 +4964,6 @@ static void lib_link_object(FileData *fd, Main *main)
}
ob->gpd = newlibadr_us(fd, ob->id.lib, ob->gpd);
- ob->duplilist = NULL;
ob->id.tag &= ~LIB_TAG_NEED_LINK;
/* if id.us==0 a new base will be created later on */
@@ -5180,6 +5182,7 @@ static void direct_link_pose(FileData *fd, bPose *pose)
link_list(fd, &pose->agroups);
pose->chanhash = NULL;
+ pose->chan_array = NULL;
for (pchan = pose->chanbase.first; pchan; pchan=pchan->next) {
pchan->bone = NULL;
@@ -5306,6 +5309,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
smd->domain->shadow = NULL;
smd->domain->tex = NULL;
smd->domain->tex_shadow = NULL;
+ smd->domain->tex_flame = NULL;
smd->domain->tex_wt = NULL;
smd->domain->coba = newdataadr(fd, smd->domain->coba);
@@ -5884,6 +5888,18 @@ static void lib_link_scene_collection(FileData *fd, Library *lib, SceneCollectio
}
}
+static void lib_link_layer_collection(FileData *fd, LayerCollection *layer_collection)
+{
+ IDP_LibLinkProperty(layer_collection->properties, fd);
+
+ for (LayerCollection *layer_collection_nested = layer_collection->layer_collections.first;
+ layer_collection_nested != NULL;
+ layer_collection_nested = layer_collection_nested->next)
+ {
+ lib_link_layer_collection(fd, layer_collection_nested);
+ }
+}
+
static void lib_link_view_layer(FileData *fd, Library *lib, ViewLayer *view_layer)
{
/* tag scene layer to update for collection tree evaluation */
@@ -5904,6 +5920,16 @@ static void lib_link_view_layer(FileData *fd, Library *lib, ViewLayer *view_laye
base->flag |= BASE_DIRTY_ENGINE_SETTINGS;
base->collection_properties = NULL;
}
+
+ for (LayerCollection *layer_collection = view_layer->layer_collections.first;
+ layer_collection != NULL;
+ layer_collection = layer_collection->next)
+ {
+ lib_link_layer_collection(fd, layer_collection);
+ }
+
+ IDP_LibLinkProperty(view_layer->properties, fd);
+ IDP_LibLinkProperty(view_layer->id_properties, fd);
}
static void lib_link_scene(FileData *fd, Main *main)
@@ -6218,6 +6244,7 @@ static void direct_link_view_layer(FileData *fd, ViewLayer *view_layer)
view_layer->properties_evaluated = NULL;
BLI_listbase_clear(&view_layer->drawdata);
+ view_layer->object_bases_array = NULL;
}
/**
@@ -6259,7 +6286,6 @@ static void direct_link_scene(FileData *fd, Scene *sce, Main *bmain)
SceneRenderLayer *srl;
sce->depsgraph_hash = NULL;
- sce->obedit = NULL;
sce->fps_info = NULL;
sce->customdata_mask_modal = 0;
sce->lay_updated = 0;
@@ -6291,7 +6317,6 @@ static void direct_link_scene(FileData *fd, Scene *sce, Main *bmain)
sce->toolsettings->imapaint.paintcursor = NULL;
sce->toolsettings->particle.paintcursor = NULL;
sce->toolsettings->particle.scene = NULL;
- sce->toolsettings->particle.view_layer = NULL;
sce->toolsettings->particle.object = NULL;
sce->toolsettings->gp_sculpt.paintcursor = NULL;
@@ -6537,8 +6562,8 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
oldnewmap_insert(fd->globmap, hook, win->workspace_hook, 0);
win->ghostwin = NULL;
+ win->gwnctx = NULL;
win->eventstate = NULL;
- win->curswin = NULL;
win->tweak = NULL;
#ifdef WIN32
win->ime_data = NULL;
@@ -6547,7 +6572,6 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
BLI_listbase_clear(&win->queue);
BLI_listbase_clear(&win->handlers);
BLI_listbase_clear(&win->modalhandlers);
- BLI_listbase_clear(&win->subwindows);
BLI_listbase_clear(&win->gesture);
BLI_listbase_clear(&win->drawdata);
@@ -6560,7 +6584,6 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
win->modalcursor = 0;
win->grabcursor = 0;
win->addmousemove = true;
- win->multisamples = 0;
win->stereo3d_format = newdataadr(fd, win->stereo3d_format);
/* multiview always fallback to anaglyph at file opening
@@ -6580,7 +6603,8 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
wm->defaultconf = NULL;
wm->addonconf = NULL;
wm->userconf = NULL;
-
+ wm->undo_stack = NULL;
+
wm->message_bus = NULL;
BLI_listbase_clear(&wm->jobs);
@@ -7350,7 +7374,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
BLI_listbase_clear(&ar->handlers);
BLI_listbase_clear(&ar->uiblocks);
ar->headerstr = NULL;
- ar->swinid = 0;
+ ar->visible = 0;
ar->type = NULL;
ar->swap = 0;
ar->do_draw = 0;
@@ -7397,8 +7421,7 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
link_list(fd, &(sc->areabase));
sc->regionbase.first = sc->regionbase.last= NULL;
sc->context = NULL;
-
- sc->mainwin = sc->subwinactive= 0; /* indices */
+ sc->active_region = NULL;
sc->swap = 0;
sc->preview = direct_link_preview_image(fd, sc->preview);
@@ -7694,12 +7717,20 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main)
BLI_remlink(&main->library, lib);
MEM_freeN(lib);
-
-
+
+ /* Now, since Blender always expect **latest** Main pointer from fd->mainlist to be the active library
+ * Main pointer, where to add all non-library data-blocks found in file next, we have to switch that
+ * 'dupli' found Main to latest position in the list!
+ * Otherwise, you get weird disappearing linked data on a rather unconsistant basis.
+ * See also T53977 for reproducible case. */
+ BLI_remlink(fd->mainlist, newmain);
+ BLI_addtail(fd->mainlist, newmain);
+
return;
}
}
}
+
/* make sure we have full path in lib->filepath */
BLI_strncpy(lib->filepath, lib->name, sizeof(lib->name));
BLI_cleanup_path(fd->relabase, lib->filepath);
@@ -8462,7 +8493,7 @@ static const char *dataname(short id_code)
case ID_WO: return "Data from WO";
case ID_SCR: return "Data from SCR";
case ID_VF: return "Data from VF";
- case ID_TXT : return "Data from TXT";
+ case ID_TXT: return "Data from TXT";
case ID_SPK: return "Data from SPK";
case ID_LP: return "Data from LP";
case ID_SO: return "Data from SO";
@@ -8596,21 +8627,21 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short
if (!id)
return blo_nextbhead(fd, bhead);
- id->tag = tag | LIB_TAG_NEED_LINK;
id->lib = main->curlib;
id->us = ID_FAKE_USERS(id);
id->icon_id = 0;
id->newid = NULL; /* Needed because .blend may have been saved with crap value here... */
id->orig_id = NULL;
+ id->recalc = 0;
/* this case cannot be direct_linked: it's just the ID part */
if (bhead->code == ID_ID) {
+ /* That way, we know which datablock needs do_versions (required currently for linking). */
+ id->tag = tag | LIB_TAG_NEED_LINK | LIB_TAG_NEW;
+
return blo_nextbhead(fd, bhead);
}
- /* That way, we know which datablock needs do_versions (required currently for linking). */
- id->tag |= LIB_TAG_NEW;
-
/* need a name for the mallocN, just for debugging and sane prints on leaks */
allocname = dataname(GS(id->name));
@@ -8619,7 +8650,11 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short
/* init pointers direct data */
direct_link_id(fd, id);
-
+
+ /* That way, we know which datablock needs do_versions (required currently for linking). */
+ /* Note: doing this after driect_link_id(), which resets that field. */
+ id->tag = tag | LIB_TAG_NEED_LINK | LIB_TAG_NEW;
+
switch (GS(id->name)) {
case ID_WM:
direct_link_windowmanager(fd, (wmWindowManager *)id);
@@ -9590,15 +9625,15 @@ static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
expand_idprops(fd, mainvar, node->prop);
for (sock = node->inputs.first; sock; sock = sock->next)
- expand_doit(fd, mainvar, sock->prop);
+ expand_idprops(fd, mainvar, sock->prop);
for (sock = node->outputs.first; sock; sock = sock->next)
- expand_doit(fd, mainvar, sock->prop);
+ expand_idprops(fd, mainvar, sock->prop);
}
for (sock = ntree->inputs.first; sock; sock = sock->next)
- expand_doit(fd, mainvar, sock->prop);
+ expand_idprops(fd, mainvar, sock->prop);
for (sock = ntree->outputs.first; sock; sock = sock->next)
- expand_doit(fd, mainvar, sock->prop);
+ expand_idprops(fd, mainvar, sock->prop);
}
static void expand_texture(FileData *fd, Main *mainvar, Tex *tex)
@@ -9999,6 +10034,18 @@ static void expand_scene_collection(FileData *fd, Main *mainvar, SceneCollection
}
}
+static void expand_layer_collection(FileData *fd, Main *mainvar, LayerCollection *layer_collection)
+{
+ expand_idprops(fd, mainvar, layer_collection->properties);
+
+ for (LayerCollection *layer_collection_nested = layer_collection->layer_collections.first;
+ layer_collection_nested != NULL;
+ layer_collection_nested = layer_collection_nested->next)
+ {
+ expand_layer_collection(fd, mainvar, layer_collection_nested);
+ }
+}
+
static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
{
SceneRenderLayer *srl;
@@ -10035,6 +10082,9 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
}
for (ViewLayer *view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
+ expand_idprops(fd, mainvar, view_layer->properties);
+ expand_idprops(fd, mainvar, view_layer->id_properties);
+
for (module = view_layer->freestyle_config.modules.first; module; module = module->next) {
if (module->script) {
expand_doit(fd, mainvar, module->script);
@@ -10047,6 +10097,13 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
}
expand_doit(fd, mainvar, lineset->linestyle);
}
+
+ for (LayerCollection *layer_collection = view_layer->layer_collections.first;
+ layer_collection != NULL;
+ layer_collection = layer_collection->next)
+ {
+ expand_layer_collection(fd, mainvar, layer_collection);
+ }
}
if (sce->r.dometext)
@@ -10882,6 +10939,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
Main *mainl = mainlist->first;
Main *mainptr;
ListBase *lbarray[MAX_LIBARRAY];
+ GHash *loaded_ids = BLI_ghash_str_new(__func__);
int a;
bool do_it = true;
@@ -10895,7 +10953,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
mainptr= mainl->next;
while (mainptr) {
if (mainvar_id_tag_any_check(mainptr, LIB_TAG_READ)) {
- // printf("found LIB_TAG_READ %s\n", mainptr->curlib->name);
+ // printf("found LIB_TAG_READ %s (%s)\n", mainptr->curlib->id.name, mainptr->curlib->name);
FileData *fd = mainptr->curlib->filedata;
@@ -10993,25 +11051,38 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
a = set_listbasepointers(mainptr, lbarray);
while (a--) {
ID *id = lbarray[a]->first;
+ ListBase pending_free_ids = {NULL};
while (id) {
ID *idn = id->next;
if (id->tag & LIB_TAG_READ) {
- ID *realid = NULL;
BLI_remlink(lbarray[a], id);
- link_id_part(basefd->reports, fd, mainptr, id, &realid);
+ /* When playing with lib renaming and such, you may end with cases where you have
+ * more than one linked ID of the same data-block from same library.
+ * This is absolutely horrible, hence we use a ghash to ensure we go back to a single
+ * linked data when loading the file... */
+ ID **realid = NULL;
+ if (!BLI_ghash_ensure_p(loaded_ids, id->name, (void ***)&realid)) {
+ link_id_part(basefd->reports, fd, mainptr, id, realid);
+ }
/* realid shall never be NULL - unless some source file/lib is broken
* (known case: some directly linked shapekey from a missing lib...). */
- /* BLI_assert(realid != NULL); */
+ /* BLI_assert(*realid != NULL); */
- change_idid_adr(mainlist, basefd, id, realid);
+ change_idid_adr(mainlist, basefd, id, *realid);
- MEM_freeN(id);
+ /* We cannot free old lib-ref placeholder ID here anymore, since we use its name
+ * as key in loaded_ids hass. */
+ BLI_addtail(&pending_free_ids, id);
}
id = idn;
}
+
+ /* Clear GHash and free all lib-ref placeholders IDs of that type now. */
+ BLI_ghash_clear(loaded_ids, NULL, NULL);
+ BLI_freelistN(&pending_free_ids);
}
BLO_expand_main(fd, mainptr);
}
@@ -11019,7 +11090,10 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
mainptr = mainptr->next;
}
}
-
+
+ BLI_ghash_free(loaded_ids, NULL, NULL);
+ loaded_ids = NULL;
+
/* test if there are unread libblocks */
/* XXX This code block is kept for 2.77, until we are sure it never gets reached anymore. Can be removed later. */
for (mainptr = mainl->next; mainptr; mainptr = mainptr->next) {
diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c
index c191e48a143..7133dee0e82 100644
--- a/source/blender/blenloader/intern/undofile.c
+++ b/source/blender/blenloader/intern/undofile.c
@@ -34,6 +34,15 @@
#include <string.h>
#include <stdio.h>
#include <math.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* open/close */
+#ifndef _WIN32
+# include <unistd.h>
+#else
+# include <io.h>
+#endif
#include "MEM_guardedalloc.h"
@@ -42,6 +51,12 @@
#include "BLI_blenlib.h"
#include "BLO_undofile.h"
+#include "BLO_readfile.h"
+
+#include "BKE_main.h"
+
+/* keep last */
+#include "BLI_strict_flags.h"
/* **************** support for memory-write, for undo buffers *************** */
@@ -51,8 +66,9 @@ void BLO_memfile_free(MemFile *memfile)
MemFileChunk *chunk;
while ((chunk = BLI_pophead(&memfile->chunks))) {
- if (chunk->ident == 0)
- MEM_freeN(chunk->buf);
+ if (chunk->is_identical == false) {
+ MEM_freeN((void *)chunk->buf);
+ }
MEM_freeN(chunk);
}
memfile->size = 0;
@@ -68,9 +84,9 @@ void BLO_memfile_merge(MemFile *first, MemFile *second)
sc = second->chunks.first;
while (fc || sc) {
if (fc && sc) {
- if (sc->ident) {
- sc->ident = 0;
- fc->ident = 1;
+ if (sc->is_identical) {
+ sc->is_identical = false;
+ fc->is_identical = true;
}
}
if (fc) fc = fc->next;
@@ -80,43 +96,99 @@ void BLO_memfile_merge(MemFile *first, MemFile *second)
BLO_memfile_free(first);
}
-void memfile_chunk_add(MemFile *compare, MemFile *current, const char *buf, unsigned int size)
+void memfile_chunk_add(
+ MemFile *memfile, const char *buf, unsigned int size,
+ MemFileChunk **compchunk_step)
{
- static MemFileChunk *compchunk = NULL;
- MemFileChunk *curchunk;
-
- /* this function inits when compare != NULL or when current == NULL */
- if (compare) {
- compchunk = compare->chunks.first;
- return;
- }
- if (current == NULL) {
- compchunk = NULL;
- return;
- }
-
- curchunk = MEM_mallocN(sizeof(MemFileChunk), "MemFileChunk");
+ MemFileChunk *curchunk = MEM_mallocN(sizeof(MemFileChunk), "MemFileChunk");
curchunk->size = size;
curchunk->buf = NULL;
- curchunk->ident = 0;
- BLI_addtail(&current->chunks, curchunk);
-
+ curchunk->is_identical = false;
+ BLI_addtail(&memfile->chunks, curchunk);
+
/* we compare compchunk with buf */
- if (compchunk) {
+ if (*compchunk_step != NULL) {
+ MemFileChunk *compchunk = *compchunk_step;
if (compchunk->size == curchunk->size) {
if (memcmp(compchunk->buf, buf, size) == 0) {
curchunk->buf = compchunk->buf;
- curchunk->ident = 1;
+ curchunk->is_identical = true;
}
}
- compchunk = compchunk->next;
+ *compchunk_step = compchunk->next;
}
-
+
/* not equal... */
if (curchunk->buf == NULL) {
- curchunk->buf = MEM_mallocN(size, "Chunk buffer");
- memcpy(curchunk->buf, buf, size);
- current->size += size;
+ char *buf_new = MEM_mallocN(size, "Chunk buffer");
+ memcpy(buf_new, buf, size);
+ curchunk->buf = buf_new;
+ memfile->size += size;
+ }
+}
+
+struct Main *BLO_memfile_main_get(struct MemFile *memfile, struct Main *oldmain, struct Scene **r_scene)
+{
+ struct Main *bmain_undo = NULL;
+ BlendFileData *bfd = BLO_read_from_memfile(oldmain, oldmain->name, memfile, NULL, BLO_READ_SKIP_NONE);
+
+ if (bfd) {
+ bmain_undo = bfd->main;
+ if (r_scene) {
+ *r_scene = bfd->curscene;
+ }
+
+ MEM_freeN(bfd);
}
+
+ return bmain_undo;
}
+
+/**
+ * Saves .blend using undo buffer.
+ *
+ * \return success.
+ */
+bool BLO_memfile_write_file(struct MemFile *memfile, const char *filename)
+{
+ MemFileChunk *chunk;
+ int file, oflags;
+
+ /* note: This is currently used for autosave and 'quit.blend', where _not_ following symlinks is OK,
+ * however if this is ever executed explicitly by the user, we may want to allow writing to symlinks.
+ */
+
+ oflags = O_BINARY | O_WRONLY | O_CREAT | O_TRUNC;
+#ifdef O_NOFOLLOW
+ /* use O_NOFOLLOW to avoid writing to a symlink - use 'O_EXCL' (CVE-2008-1103) */
+ oflags |= O_NOFOLLOW;
+#else
+ /* TODO(sergey): How to deal with symlinks on windows? */
+# ifndef _MSC_VER
+# warning "Symbolic links will be followed on undo save, possibly causing CVE-2008-1103"
+# endif
+#endif
+ file = BLI_open(filename, oflags, 0666);
+
+ if (file == -1) {
+ fprintf(stderr, "Unable to save '%s': %s\n",
+ filename, errno ? strerror(errno) : "Unknown error opening file");
+ return false;
+ }
+
+ for (chunk = memfile->chunks.first; chunk; chunk = chunk->next) {
+ if ((size_t)write(file, chunk->buf, chunk->size) != chunk->size) {
+ break;
+ }
+ }
+
+ close(file);
+
+ if (chunk) {
+ fprintf(stderr, "Unable to save '%s': %s\n",
+ filename, errno ? strerror(errno) : "Unknown error writing file");
+ return false;
+ }
+ return true;
+}
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 7036470c8e4..f5a4a33860f 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -52,7 +52,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_node_types.h"
-#include "DNA_object_fluidsim.h" // NT
+#include "DNA_object_fluidsim_types.h"
#include "DNA_object_types.h"
#include "DNA_view3d_types.h"
#include "DNA_screen_types.h"
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 3ac934f7de7..f7301fe4664 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -41,7 +41,7 @@
#include "DNA_linestyle_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_object_fluidsim.h" // NT
+#include "DNA_object_fluidsim_types.h"
#include "DNA_object_types.h"
#include "DNA_property_types.h"
#include "DNA_text_types.h"
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index 0800437c3d2..7228c3522f0 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -45,7 +45,7 @@
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "DNA_screen_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
#include "DNA_mask_types.h"
#include "DNA_mesh_types.h"
@@ -1756,6 +1756,24 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
+ if (!MAIN_VERSION_ATLEAST(main, 279, 3)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "SmokeDomainSettings", "float", "clipping")) {
+ Object *ob;
+ ModifierData *md;
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Smoke) {
+ SmokeModifierData *smd = (SmokeModifierData *)md;
+ if (smd->domain) {
+ smd->domain->clipping = 1e-3f;
+ }
+ }
+ }
+ }
+ }
+ }
+
{
/* Fix for invalid state of screen due to bug in older versions. */
for (bScreen *sc = main->screen.first; sc; sc = sc->id.next) {
@@ -1799,6 +1817,23 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
}
+
+ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+ int preset = scene->r.ffcodecdata.ffmpeg_preset;
+ if (preset == FFM_PRESET_NONE || preset >= FFM_PRESET_GOOD) {
+ continue;
+ }
+ if (preset <= FFM_PRESET_FAST) {
+ preset = FFM_PRESET_REALTIME;
+ }
+ else if (preset >= FFM_PRESET_SLOW) {
+ preset = FFM_PRESET_BEST;
+ }
+ else {
+ preset = FFM_PRESET_GOOD;
+ }
+ scene->r.ffcodecdata.ffmpeg_preset = preset;
+ }
}
}
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 2f07ca43ff0..50b7f736a67 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -505,7 +505,7 @@ void do_versions_after_linking_280(Main *main)
soutliner->outlinevis = SO_VIEW_LAYER;
- if (BLI_listbase_count_ex(&layer->layer_collections, 2) == 1) {
+ if (BLI_listbase_count_at_most(&layer->layer_collections, 2) == 1) {
if (soutliner->treestore == NULL) {
soutliner->treestore = BLI_mempool_create(
sizeof(TreeStoreElem), 1, 512, BLI_MEMPOOL_ALLOW_ITER);
@@ -546,6 +546,18 @@ void do_versions_after_linking_280(Main *main)
}
}
+ if (!MAIN_VERSION_ATLEAST(main, 280, 3)) {
+ /* Due to several changes to particle RNA and draw code particles from older files may no longer
+ * be visible. Here we correct this by setting a default draw size for those files. */
+ for (Object *object = main->object.first; object; object = object->id.next) {
+ for (ParticleSystem *psys = object->particlesystem.first; psys; psys=psys->next) {
+ if(psys->part->draw_size == 0.0f) {
+ psys->part->draw_size = 0.1f;
+ }
+ }
+ }
+ }
+
{
for (WorkSpace *workspace = main->workspaces.first; workspace; workspace = workspace->id.next) {
if (workspace->view_layer) {
@@ -611,7 +623,7 @@ void do_versions_after_linking_280(Main *main)
#endif
if (object->particlesystem.first) {
object->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT;
- for (ParticleSystem *psys = object->particlesystem.first; psys; psys=psys->next) {
+ for (ParticleSystem *psys = object->particlesystem.first; psys; psys = psys->next) {
if (psys->part->draw & PART_DRAW_EMITTER) {
object->duplicator_visibility_flag |= OB_DUPLI_FLAG_RENDER;
#ifndef VERSION_280_SUBVERSION_4
@@ -701,6 +713,10 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
}
+
+ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+ scene->r.gauss = 1.5f;
+ }
}
if (!MAIN_VERSION_ATLEAST(main, 280, 1)) {
@@ -898,11 +914,11 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
SpaceOops *so = (SpaceOops *)sl;
if (!ELEM(so->outlinevis,
- SO_SCENES,
- SO_GROUPS,
- SO_LIBRARIES,
- SO_SEQUENCE,
- SO_DATABLOCKS,
+ SO_SCENES,
+ SO_GROUPS,
+ SO_LIBRARIES,
+ SO_SEQUENCE,
+ SO_DATABLOCKS,
SO_ID_ORPHANS,
SO_VIEW_LAYER,
SO_COLLECTIONS))
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index f5f6531754a..b09c7d77e59 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -58,7 +58,7 @@ void BLO_update_defaults_userpref_blend(void)
{
/* defaults from T37518 */
- U.uiflag |= USER_ZBUF_CURSOR;
+ U.uiflag |= USER_DEPTH_CURSOR;
U.uiflag |= USER_QUIT_PROMPT;
U.uiflag |= USER_CONTINUOUS_MOUSE;
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 0af1c3951ad..b8744b71812 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -58,7 +58,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_nla_types.h"
#include "DNA_node_types.h"
-#include "DNA_object_fluidsim.h" // NT
+#include "DNA_object_fluidsim_types.h"
#include "DNA_object_types.h"
#include "DNA_property_types.h"
#include "DNA_view3d_types.h"
@@ -2770,13 +2770,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
for (part = main->particle.first; part; part = part->id.next) {
if (part->ren_child_nbr == 0)
part->ren_child_nbr = part->child_nbr;
-
- if (part->simplify_refsize == 0) {
- part->simplify_refsize = 1920;
- part->simplify_rate = 1.0f;
- part->simplify_transition = 0.1f;
- part->simplify_viewport = 0.8f;
- }
}
for (wrld = main->world.first; wrld; wrld = wrld->id.next) {
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 3bd2f67ab86..973fac1d13a 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -134,7 +134,7 @@
#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_packedFile_types.h"
#include "DNA_particle_types.h"
#include "DNA_lightprobe_types.h"
@@ -208,8 +208,11 @@
#define MYWRITE_BUFFER_SIZE (MEM_SIZE_OPTIMAL(1 << 17)) /* 128kb */
#define MYWRITE_MAX_CHUNK (MEM_SIZE_OPTIMAL(1 << 15)) /* ~32kb */
+/** Use if we want to store how many bytes have been written to the file. */
+// #define USE_WRITE_DATA_LEN
-/** \name Small API to handle compression.
+/* -------------------------------------------------------------------- */
+/** \name Internal Write Wrapper's (Abstracts Compression)
* \{ */
typedef enum {
@@ -313,20 +316,41 @@ static void ww_handle_init(eWriteWrapType ww_type, WriteWrap *r_ww)
/** \} */
-
+/* -------------------------------------------------------------------- */
+/** \name Write Data Type & Functions
+ * \{ */
typedef struct {
const struct SDNA *sdna;
- unsigned char *buf;
- MemFile *compare, *current;
+ /** Use for file and memory writing (fixed size of #MYWRITE_BUFFER_SIZE). */
+ uchar *buf;
+ /** Number of bytes used in #WriteData.buf (flushed when exceeded). */
+ int buf_used_len;
+
+#ifdef USE_WRITE_DATA_LEN
+ /** Total number of bytes written. */
+ size_t write_len;
+#endif
- int tot, count;
+ /** Set on unlikely case of an error (ignores further file writing). */
bool error;
- /* Wrap writing, so we can use zlib or
+ /** #MemFile writing (used for undo). */
+ struct {
+ MemFile *current;
+ MemFile *compare;
+ /** Use to de-duplicate chunks when writing. */
+ MemFileChunk *compare_chunk;
+ } mem;
+ /** When true, write to #WriteData.current, could also call 'is_undo'. */
+ bool use_memfile;
+
+ /**
+ * Wrap writing, so we can use zlib or
* other compression types later, see: G_FILE_COMPRESS
- * Will be NULL for UNDO. */
+ * Will be NULL for UNDO.
+ */
WriteWrap *ww;
#ifdef USE_BMESH_SAVE_AS_COMPAT
@@ -358,8 +382,8 @@ static void writedata_do_write(WriteData *wd, const void *mem, int memlen)
}
/* memory based save */
- if (wd->current) {
- memfile_chunk_add(NULL, wd->current, mem, memlen);
+ if (wd->use_memfile) {
+ memfile_chunk_add(wd->mem.current, mem, memlen, &wd->mem.compare_chunk);
}
else {
if (wd->ww->write(wd->ww, mem, memlen) != memlen) {
@@ -374,7 +398,11 @@ static void writedata_free(WriteData *wd)
MEM_freeN(wd);
}
-/***/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Local Writing API 'mywrite'
+ * \{ */
/**
* Flush helps the de-duplicating memory for undo-save by logically segmenting data,
@@ -382,9 +410,9 @@ static void writedata_free(WriteData *wd)
*/
static void mywrite_flush(WriteData *wd)
{
- if (wd->count) {
- writedata_do_write(wd, wd->buf, wd->count);
- wd->count = 0;
+ if (wd->buf_used_len) {
+ writedata_do_write(wd, wd->buf, wd->buf_used_len);
+ wd->buf_used_len = 0;
}
}
@@ -392,7 +420,6 @@ static void mywrite_flush(WriteData *wd)
* Low level WRITE(2) wrapper that buffers data
* \param adr Pointer to new chunk of data
* \param len Length of new chunk of data
- * \warning Talks to other functions with global parameters
*/
static void mywrite(WriteData *wd, const void *adr, int len)
{
@@ -400,19 +427,21 @@ static void mywrite(WriteData *wd, const void *adr, int len)
return;
}
- if (adr == NULL) {
+ if (UNLIKELY(adr == NULL)) {
BLI_assert(0);
return;
}
- wd->tot += len;
+#ifdef USE_WRITE_DATA_LEN
+ wd->write_len += len;
+#endif
/* if we have a single big chunk, write existing data in
* buffer and write out big chunk in smaller pieces */
if (len > MYWRITE_MAX_CHUNK) {
- if (wd->count) {
- writedata_do_write(wd, wd->buf, wd->count);
- wd->count = 0;
+ if (wd->buf_used_len) {
+ writedata_do_write(wd, wd->buf, wd->buf_used_len);
+ wd->buf_used_len = 0;
}
do {
@@ -426,14 +455,14 @@ static void mywrite(WriteData *wd, const void *adr, int len)
}
/* if data would overflow buffer, write out the buffer */
- if (len + wd->count > MYWRITE_BUFFER_SIZE - 1) {
- writedata_do_write(wd, wd->buf, wd->count);
- wd->count = 0;
+ if (len + wd->buf_used_len > MYWRITE_BUFFER_SIZE - 1) {
+ writedata_do_write(wd, wd->buf, wd->buf_used_len);
+ wd->buf_used_len = 0;
}
/* append data at end of buffer */
- memcpy(&wd->buf[wd->count], adr, len);
- wd->count += len;
+ memcpy(&wd->buf[wd->buf_used_len], adr, len);
+ wd->buf_used_len += len;
}
/**
@@ -443,19 +472,17 @@ static void mywrite(WriteData *wd, const void *adr, int len)
* \param current The current memory file (can be NULL).
* \warning Talks to other functions with global parameters
*/
-static WriteData *bgnwrite(WriteWrap *ww, MemFile *compare, MemFile *current)
+static WriteData *mywrite_begin(WriteWrap *ww, MemFile *compare, MemFile *current)
{
WriteData *wd = writedata_new(ww);
- if (wd == NULL) {
- return NULL;
+ if (current != NULL) {
+ wd->mem.current = current;
+ wd->mem.compare = compare;
+ wd->mem.compare_chunk = compare ? compare->chunks.first : NULL;
+ wd->use_memfile = true;
}
- wd->compare = compare;
- wd->current = current;
- /* this inits comparing */
- memfile_chunk_add(compare, NULL, NULL, 0);
-
return wd;
}
@@ -465,11 +492,11 @@ static WriteData *bgnwrite(WriteWrap *ww, MemFile *compare, MemFile *current)
* \return unknown global variable otherwise
* \warning Talks to other functions with global parameters
*/
-static bool endwrite(WriteData *wd)
+static bool mywrite_end(WriteData *wd)
{
- if (wd->count) {
- writedata_do_write(wd, wd->buf, wd->count);
- wd->count = 0;
+ if (wd->buf_used_len) {
+ writedata_do_write(wd, wd->buf, wd->buf_used_len);
+ wd->buf_used_len = 0;
}
const bool err = wd->error;
@@ -478,7 +505,11 @@ static bool endwrite(WriteData *wd)
return err;
}
-/* ********** WRITE FILE ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Generic DNA File Writing
+ * \{ */
static void writestruct_at_address_nr(
WriteData *wd, int filecode, const int struct_nr, int nr,
@@ -604,8 +635,14 @@ static void writelist_id(WriteData *wd, int filecode, const char *structname, co
#define writelist(wd, filecode, struct_id, lb) \
writelist_nr(wd, filecode, SDNA_TYPE_FROM_STRUCT(struct_id), lb)
-/* *************** writing some direct data structs used in more code parts **************** */
-/*These functions are used by blender's .blend system for file saving/loading.*/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Typed DNA File Writing
+ *
+ * These functions are used by blender's .blend system for file saving/loading.
+ * \{ */
+
void IDP_WriteProperty_OnlyData(const IDProperty *prop, void *wd);
void IDP_WriteProperty(const IDProperty *prop, void *wd);
@@ -832,7 +869,7 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves)
static void write_action(WriteData *wd, bAction *act)
{
- if (act->id.us > 0 || wd->current) {
+ if (act->id.us > 0 || wd->use_memfile) {
writestruct(wd, ID_AC, bAction, 1, act);
write_iddata(wd, &act->id);
@@ -940,7 +977,7 @@ static void write_node_socket(WriteData *wd, bNodeTree *UNUSED(ntree), bNode *no
{
#ifdef USE_NODE_COMPAT_CUSTOMNODES
/* forward compatibility code, so older blenders still open (not for undo) */
- if (wd->current == NULL) {
+ if (wd->use_memfile == false) {
sock->stack_type = 1;
if (node->type == NODE_GROUP) {
@@ -1060,7 +1097,7 @@ static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree)
* Not ideal (there is no ideal solution here), but should do for now. */
NodeGlare *ndg = node->storage;
/* Not in undo case. */
- if (!wd->current) {
+ if (wd->use_memfile == false) {
switch (ndg->type) {
case 2: /* Grrrr! magic numbers :( */
ndg->angle = ndg->streaks;
@@ -1178,7 +1215,7 @@ static void write_renderinfo(WriteData *wd, Main *mainvar)
}
}
-static void write_keymapitem(WriteData *wd, wmKeyMapItem *kmi)
+static void write_keymapitem(WriteData *wd, const wmKeyMapItem *kmi)
{
writestruct(wd, DATA, wmKeyMapItem, 1, kmi);
if (kmi->properties) {
@@ -1186,26 +1223,18 @@ static void write_keymapitem(WriteData *wd, wmKeyMapItem *kmi)
}
}
-static void write_userdef(WriteData *wd)
+static void write_userdef(WriteData *wd, const UserDef *userdef)
{
- bTheme *btheme;
- wmKeyMap *keymap;
- wmKeyMapItem *kmi;
- wmKeyMapDiffItem *kmdi;
- bAddon *bext;
- bPathCompare *path_cmp;
- uiStyle *style;
-
- writestruct(wd, USER, UserDef, 1, &U);
+ writestruct(wd, USER, UserDef, 1, userdef);
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ for (const bTheme *btheme = userdef->themes.first; btheme; btheme = btheme->next) {
writestruct(wd, DATA, bTheme, 1, btheme);
}
- for (keymap = U.user_keymaps.first; keymap; keymap = keymap->next) {
+ for (const wmKeyMap *keymap = userdef->user_keymaps.first; keymap; keymap = keymap->next) {
writestruct(wd, DATA, wmKeyMap, 1, keymap);
- for (kmdi = keymap->diff_items.first; kmdi; kmdi = kmdi->next) {
+ for (const wmKeyMapDiffItem *kmdi = keymap->diff_items.first; kmdi; kmdi = kmdi->next) {
writestruct(wd, DATA, wmKeyMapDiffItem, 1, kmdi);
if (kmdi->remove_item) {
write_keymapitem(wd, kmdi->remove_item);
@@ -1215,23 +1244,23 @@ static void write_userdef(WriteData *wd)
}
}
- for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
+ for (const wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
write_keymapitem(wd, kmi);
}
}
- for (bext = U.addons.first; bext; bext = bext->next) {
+ for (const bAddon *bext = userdef->addons.first; bext; bext = bext->next) {
writestruct(wd, DATA, bAddon, 1, bext);
if (bext->prop) {
IDP_WriteProperty(bext->prop, wd);
}
}
- for (path_cmp = U.autoexec_paths.first; path_cmp; path_cmp = path_cmp->next) {
+ for (const bPathCompare *path_cmp = userdef->autoexec_paths.first; path_cmp; path_cmp = path_cmp->next) {
writestruct(wd, DATA, bPathCompare, 1, path_cmp);
}
- for (style = U.uistyles.first; style; style = style->next) {
+ for (const uiStyle *style = userdef->uistyles.first; style; style = style->next) {
writestruct(wd, DATA, uiStyle, 1, style);
}
}
@@ -1329,7 +1358,7 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches)
static void write_particlesettings(WriteData *wd, ParticleSettings *part)
{
- if (part->id.us > 0 || wd->current) {
+ if (part->id.us > 0 || wd->use_memfile) {
/* write LibData */
writestruct(wd, ID_PA, ParticleSettings, 1, part);
write_iddata(wd, &part->id);
@@ -1347,19 +1376,22 @@ static void write_particlesettings(WriteData *wd, ParticleSettings *part)
if (part->roughcurve) {
write_curvemapping(wd, part->roughcurve);
}
+ if (part->twistcurve) {
+ write_curvemapping(wd, part->twistcurve);
+ }
for (ParticleDupliWeight *dw = part->dupliweights.first; dw; dw = dw->next) {
/* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */
if (dw->ob != NULL) {
dw->index = 0;
if (part->dup_group) { /* can be NULL if lining fails or set to None */
- FOREACH_GROUP_OBJECT(part->dup_group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
{
if (object != dw->ob) {
dw->index++;
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
}
writestruct(wd, DATA, ParticleDupliWeight, 1, dw);
@@ -1935,7 +1967,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
static void write_object(WriteData *wd, Object *ob)
{
- if (ob->id.us > 0 || wd->current) {
+ if (ob->id.us > 0 || wd->use_memfile) {
/* write LibData */
writestruct(wd, ID_OB, Object, 1, ob);
write_iddata(wd, &ob->id);
@@ -1999,7 +2031,7 @@ static void write_object(WriteData *wd, Object *ob)
static void write_vfont(WriteData *wd, VFont *vf)
{
- if (vf->id.us > 0 || wd->current) {
+ if (vf->id.us > 0 || wd->use_memfile) {
/* write LibData */
writestruct(wd, ID_VF, VFont, 1, vf);
write_iddata(wd, &vf->id);
@@ -2016,7 +2048,7 @@ static void write_vfont(WriteData *wd, VFont *vf)
static void write_key(WriteData *wd, Key *key)
{
- if (key->id.us > 0 || wd->current) {
+ if (key->id.us > 0 || wd->use_memfile) {
/* write LibData */
writestruct(wd, ID_KE, Key, 1, key);
write_iddata(wd, &key->id);
@@ -2037,7 +2069,7 @@ static void write_key(WriteData *wd, Key *key)
static void write_camera(WriteData *wd, Camera *cam)
{
- if (cam->id.us > 0 || wd->current) {
+ if (cam->id.us > 0 || wd->use_memfile) {
/* write LibData */
writestruct(wd, ID_CA, Camera, 1, cam);
write_iddata(wd, &cam->id);
@@ -2054,7 +2086,7 @@ static void write_camera(WriteData *wd, Camera *cam)
static void write_mball(WriteData *wd, MetaBall *mb)
{
- if (mb->id.us > 0 || wd->current) {
+ if (mb->id.us > 0 || wd->use_memfile) {
/* write LibData */
writestruct(wd, ID_MB, MetaBall, 1, mb);
write_iddata(wd, &mb->id);
@@ -2073,7 +2105,7 @@ static void write_mball(WriteData *wd, MetaBall *mb)
static void write_curve(WriteData *wd, Curve *cu)
{
- if (cu->id.us > 0 || wd->current) {
+ if (cu->id.us > 0 || wd->use_memfile) {
/* write LibData */
writestruct(wd, ID_CU, Curve, 1, cu);
write_iddata(wd, &cu->id);
@@ -2174,7 +2206,7 @@ static void write_customdata(
int i;
/* write external customdata (not for undo) */
- if (data->external && !wd->current) {
+ if (data->external && (wd->use_memfile == false)) {
CustomData_external_write(data, id, CD_MASK_MESH, count, 0);
}
@@ -2244,7 +2276,7 @@ static void write_mesh(WriteData *wd, Mesh *mesh)
CustomDataLayer *llayers = NULL, llayers_buff[CD_TEMP_CHUNK_SIZE];
CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
- if (mesh->id.us > 0 || wd->current) {
+ if (mesh->id.us > 0 || wd->use_memfile) {
/* write LibData */
if (!save_for_old_blender) {
/* write a copy of the mesh, don't modify in place because it is
@@ -2386,7 +2418,7 @@ static void write_mesh(WriteData *wd, Mesh *mesh)
static void write_lattice(WriteData *wd, Lattice *lt)
{
- if (lt->id.us > 0 || wd->current) {
+ if (lt->id.us > 0 || wd->use_memfile) {
/* write LibData */
writestruct(wd, ID_LT, Lattice, 1, lt);
write_iddata(wd, &lt->id);
@@ -2405,7 +2437,7 @@ static void write_lattice(WriteData *wd, Lattice *lt)
static void write_image(WriteData *wd, Image *ima)
{
- if (ima->id.us > 0 || wd->current) {
+ if (ima->id.us > 0 || wd->use_memfile) {
ImagePackedFile *imapf;
/* Some trickery to keep forward compatibility of packed images. */
@@ -2441,7 +2473,7 @@ static void write_image(WriteData *wd, Image *ima)
static void write_texture(WriteData *wd, Tex *tex)
{
- if (tex->id.us > 0 || wd->current) {
+ if (tex->id.us > 0 || wd->use_memfile) {
/* write LibData */
writestruct(wd, ID_TE, Tex, 1, tex);
write_iddata(wd, &tex->id);
@@ -2485,7 +2517,7 @@ static void write_texture(WriteData *wd, Tex *tex)
static void write_material(WriteData *wd, Material *ma)
{
- if (ma->id.us > 0 || wd->current) {
+ if (ma->id.us > 0 || wd->use_memfile) {
/* write LibData */
writestruct(wd, ID_MA, Material, 1, ma);
write_iddata(wd, &ma->id);
@@ -2519,7 +2551,7 @@ static void write_material(WriteData *wd, Material *ma)
static void write_world(WriteData *wd, World *wrld)
{
- if (wrld->id.us > 0 || wd->current) {
+ if (wrld->id.us > 0 || wd->use_memfile) {
/* write LibData */
writestruct(wd, ID_WO, World, 1, wrld);
write_iddata(wd, &wrld->id);
@@ -2546,7 +2578,7 @@ static void write_world(WriteData *wd, World *wrld)
static void write_lamp(WriteData *wd, Lamp *la)
{
- if (la->id.us > 0 || wd->current) {
+ if (la->id.us > 0 || wd->use_memfile) {
/* write LibData */
writestruct(wd, ID_LA, Lamp, 1, la);
write_iddata(wd, &la->id);
@@ -2863,7 +2895,7 @@ static void write_scene(WriteData *wd, Scene *sce)
static void write_gpencil(WriteData *wd, bGPdata *gpd)
{
- if (gpd->id.us > 0 || wd->current) {
+ if (gpd->id.us > 0 || wd->use_memfile) {
/* write gpd data block to file */
writestruct(wd, ID_GD, bGPdata, 1, gpd);
write_iddata(wd, &gpd->id);
@@ -2957,7 +2989,7 @@ static void write_soops(WriteData *wd, SpaceOops *so)
if (ts) {
SpaceOops so_flat = *so;
- int elems = BLI_mempool_count(ts);
+ int elems = BLI_mempool_len(ts);
/* linearize mempool to array */
TreeStoreElem *data = elems ? BLI_mempool_as_arrayN(ts, "TreeStoreElem") : NULL;
@@ -3178,7 +3210,7 @@ static void write_bone(WriteData *wd, Bone *bone)
static void write_armature(WriteData *wd, bArmature *arm)
{
- if (arm->id.us > 0 || wd->current) {
+ if (arm->id.us > 0 || wd->use_memfile) {
writestruct(wd, ID_AR, bArmature, 1, arm);
write_iddata(wd, &arm->id);
@@ -3221,7 +3253,7 @@ static void write_text(WriteData *wd, Text *text)
static void write_speaker(WriteData *wd, Speaker *spk)
{
- if (spk->id.us > 0 || wd->current) {
+ if (spk->id.us > 0 || wd->use_memfile) {
/* write LibData */
writestruct(wd, ID_SPK, Speaker, 1, spk);
write_iddata(wd, &spk->id);
@@ -3234,7 +3266,7 @@ static void write_speaker(WriteData *wd, Speaker *spk)
static void write_sound(WriteData *wd, bSound *sound)
{
- if (sound->id.us > 0 || wd->current) {
+ if (sound->id.us > 0 || wd->use_memfile) {
/* write LibData */
writestruct(wd, ID_SO, bSound, 1, sound);
write_iddata(wd, &sound->id);
@@ -3249,7 +3281,7 @@ static void write_sound(WriteData *wd, bSound *sound)
static void write_probe(WriteData *wd, LightProbe *prb)
{
- if (prb->id.us > 0 || wd->current) {
+ if (prb->id.us > 0 || wd->use_memfile) {
/* write LibData */
writestruct(wd, ID_LP, LightProbe, 1, prb);
write_iddata(wd, &prb->id);
@@ -3262,7 +3294,7 @@ static void write_probe(WriteData *wd, LightProbe *prb)
static void write_group(WriteData *wd, Group *group)
{
- if (group->id.us > 0 || wd->current) {
+ if (group->id.us > 0 || wd->use_memfile) {
/* write LibData */
writestruct(wd, ID_GR, Group, 1, group);
write_iddata(wd, &group->id);
@@ -3275,7 +3307,7 @@ static void write_group(WriteData *wd, Group *group)
static void write_nodetree(WriteData *wd, bNodeTree *ntree)
{
- if (ntree->id.us > 0 || wd->current) {
+ if (ntree->id.us > 0 || wd->use_memfile) {
writestruct(wd, ID_NT, bNodeTree, 1, ntree);
/* Note that trees directly used by other IDs (materials etc.) are not 'real' ID, they cannot
* be linked, etc., so we write actual id data here only, for 'real' ID trees. */
@@ -3357,7 +3389,7 @@ static void customnodes_free_deprecated_data(Main *mainvar)
static void write_brush(WriteData *wd, Brush *brush)
{
- if (brush->id.us > 0 || wd->current) {
+ if (brush->id.us > 0 || wd->use_memfile) {
writestruct(wd, ID_BR, Brush, 1, brush);
write_iddata(wd, &brush->id);
@@ -3372,7 +3404,7 @@ static void write_brush(WriteData *wd, Brush *brush)
static void write_palette(WriteData *wd, Palette *palette)
{
- if (palette->id.us > 0 || wd->current) {
+ if (palette->id.us > 0 || wd->use_memfile) {
PaletteColor *color;
writestruct(wd, ID_PAL, Palette, 1, palette);
write_iddata(wd, &palette->id);
@@ -3385,7 +3417,7 @@ static void write_palette(WriteData *wd, Palette *palette)
static void write_paintcurve(WriteData *wd, PaintCurve *pc)
{
- if (pc->id.us > 0 || wd->current) {
+ if (pc->id.us > 0 || wd->use_memfile) {
writestruct(wd, ID_PC, PaintCurve, 1, pc);
write_iddata(wd, &pc->id);
@@ -3433,7 +3465,7 @@ static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction
static void write_movieclip(WriteData *wd, MovieClip *clip)
{
- if (clip->id.us > 0 || wd->current) {
+ if (clip->id.us > 0 || wd->use_memfile) {
MovieTracking *tracking = &clip->tracking;
MovieTrackingObject *object;
@@ -3463,7 +3495,7 @@ static void write_movieclip(WriteData *wd, MovieClip *clip)
static void write_mask(WriteData *wd, Mask *mask)
{
- if (mask->id.us > 0 || wd->current) {
+ if (mask->id.us > 0 || wd->use_memfile) {
MaskLayer *masklay;
writestruct(wd, ID_MSK, Mask, 1, mask);
@@ -3768,7 +3800,7 @@ static void write_linestyle_geometry_modifiers(WriteData *wd, ListBase *modifier
static void write_linestyle(WriteData *wd, FreestyleLineStyle *linestyle)
{
- if (linestyle->id.us > 0 || wd->current) {
+ if (linestyle->id.us > 0 || wd->use_memfile) {
writestruct(wd, ID_LS, FreestyleLineStyle, 1, linestyle);
write_iddata(wd, &linestyle->id);
@@ -3794,7 +3826,7 @@ static void write_linestyle(WriteData *wd, FreestyleLineStyle *linestyle)
static void write_cachefile(WriteData *wd, CacheFile *cache_file)
{
- if (cache_file->id.us > 0 || wd->current) {
+ if (cache_file->id.us > 0 || wd->use_memfile) {
writestruct(wd, ID_CF, CacheFile, 1, cache_file);
if (cache_file->adt) {
@@ -3812,6 +3844,7 @@ static void write_workspace(WriteData *wd, WorkSpace *workspace)
writelist(wd, DATA, WorkSpaceLayout, layouts);
writelist(wd, DATA, WorkSpaceDataRelation, &workspace->hook_layout_relations);
writelist(wd, DATA, WorkSpaceDataRelation, &workspace->scene_viewlayer_relations);
+ writelist(wd, DATA, wmOwnerID, &workspace->owner_ids);
writelist(wd, DATA, TransformOrientation, transform_orientations);
}
@@ -3881,7 +3914,7 @@ static void write_libraries(WriteData *wd, Main *main)
PackedFile *pf = main->curlib->packedfile;
writestruct(wd, DATA, PackedFile, 1, pf);
writedata(wd, DATA, pf->size, pf->data);
- if (wd->current == NULL) {
+ if (wd->use_memfile == false) {
printf("write packed .blend: %s\n", main->curlib->name);
}
}
@@ -3909,7 +3942,7 @@ static void write_libraries(WriteData *wd, Main *main)
* - for undofile, curscene needs to be saved */
static void write_global(WriteData *wd, int fileflags, Main *mainvar)
{
- const bool is_undo = (wd->current != NULL);
+ const bool is_undo = wd->use_memfile;
FileGlobal fg;
bScreen *screen;
Scene *scene;
@@ -3966,6 +3999,12 @@ static void write_thumb(WriteData *wd, const BlendThumbnail *thumb)
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name File Writing (Private)
+ * \{ */
+
/* if MemFile * there's filesave to memory */
static bool write_file_handle(
Main *mainvar,
@@ -3980,7 +4019,7 @@ static bool write_file_handle(
blo_split_main(&mainlist, mainvar);
- wd = bgnwrite(ww, compare, current);
+ wd = mywrite_begin(ww, compare, current);
#ifdef USE_BMESH_SAVE_AS_COMPAT
wd->use_mesh_compat = (write_flags & G_FILE_MESH_COMPAT) != 0;
@@ -4009,7 +4048,7 @@ static bool write_file_handle(
* avoid thumbnail detecting changes because of this. */
mywrite_flush(wd);
- OverrideStaticStorage *override_storage = !wd->current ? BKE_override_static_operations_store_initialize() : NULL;
+ OverrideStaticStorage *override_storage = wd->use_memfile ? NULL : BKE_override_static_operations_store_initialize();
/* This outer loop allows to save first datablocks from real mainvar, then the temp ones from override process,
* if needed, without duplicating whole code. */
@@ -4174,7 +4213,7 @@ static bool write_file_handle(
mywrite_flush(wd);
if (write_flags & G_FILE_USERPREFS) {
- write_userdef(wd);
+ write_userdef(wd, &U);
}
/* Write DNA last, because (to be implemented) test for which structs are written.
@@ -4201,7 +4240,7 @@ static bool write_file_handle(
blo_join_main(&mainlist);
- return endwrite(wd);
+ return mywrite_end(wd);
}
/* do reverse file history: .blend1 -> .blend2, .blend -> .blend1 */
@@ -4246,6 +4285,12 @@ static bool do_history(const char *name, ReportList *reports)
return 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name File Writing (Public)
+ * \{ */
+
/**
* \return Success.
*/
@@ -4359,3 +4404,5 @@ bool BLO_write_file_mem(Main *mainvar, MemFile *compare, MemFile *current, int w
return (err == 0);
}
+
+/** \} */
diff --git a/source/blender/blentranslation/msgfmt/msgfmt.c b/source/blender/blentranslation/msgfmt/msgfmt.c
index 49f850f200c..a155cce53a5 100644
--- a/source/blender/blentranslation/msgfmt/msgfmt.c
+++ b/source/blender/blentranslation/msgfmt/msgfmt.c
@@ -186,7 +186,7 @@ typedef struct Offset {
/* Return the generated binary output. */
static char *generate(GHash *messages, size_t *r_output_size)
{
- const uint32_t num_keys = BLI_ghash_size(messages);
+ const uint32_t num_keys = BLI_ghash_len(messages);
/* Get list of sorted keys. */
char **keys = get_keys_sorted(messages, num_keys);
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 36b2f9cadf7..7e35866887d 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -685,7 +685,7 @@ int bmesh_elem_check(void *element, const char htype)
err |= IS_FACE_LOOP_WRONG_RADIAL_LENGTH;
}
- if (bmesh_disk_count_ex(l_iter->v, 2) < 2) {
+ if (bmesh_disk_count_at_most(l_iter->v, 2) < 2) {
err |= IS_FACE_LOOP_WRONG_DISK_LENGTH;
}
}
@@ -1282,8 +1282,8 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del)
}
/* create region face */
- f_new = BLI_array_count(edges) ?
- BM_face_create_ngon(bm, v1, v2, edges, BLI_array_count(edges), faces[0], BM_CREATE_NOP) : NULL;
+ f_new = BLI_array_len(edges) ?
+ BM_face_create_ngon(bm, v1, v2, edges, BLI_array_len(edges), faces[0], BM_CREATE_NOP) : NULL;
if (UNLIKELY(f_new == NULL)) {
/* Invalid boundary region to join faces */
goto error;
@@ -1347,11 +1347,11 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del)
/* delete old geometry */
if (do_del) {
- for (i = 0; i < BLI_array_count(deledges); i++) {
+ for (i = 0; i < BLI_array_len(deledges); i++) {
BM_edge_kill(bm, deledges[i]);
}
- for (i = 0; i < BLI_array_count(delverts); i++) {
+ for (i = 0; i < BLI_array_len(delverts); i++) {
BM_vert_kill(bm, delverts[i]);
}
}
@@ -1785,7 +1785,7 @@ BMEdge *bmesh_kernel_join_edge_kill_vert(
return NULL;
}
- if (bmesh_disk_count_ex(v_kill, 3) == 2) {
+ if (bmesh_disk_count_at_most(v_kill, 3) == 2) {
#ifndef NDEBUG
int valence1, valence2;
BMLoop *l;
@@ -2423,9 +2423,10 @@ static void bmesh_kernel_vert_separate__cleanup(BMesh *bm, LinkNode *edges_separ
/* don't visit again */
n_prev->next = n_step->next;
}
- } while ((void)
- (n_prev = n_step),
- (n_step = n_step->next));
+ else {
+ n_prev = n_step;
+ }
+ } while ((n_step = n_step->next));
} while ((n_orig = n_orig->next) && n_orig->next);
} while ((edges_separate = edges_separate->next));
diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c
index 96154f051f9..9fe28561b93 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.c
+++ b/source/blender/bmesh/intern/bmesh_iterators.c
@@ -430,7 +430,7 @@ int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const
void bmiter__elem_of_mesh_begin(struct BMIter__elem_of_mesh *iter)
{
#ifdef USE_IMMUTABLE_ASSERT
- ((BMIter *)iter)->count = BLI_mempool_count(iter->pooliter.pool);
+ ((BMIter *)iter)->count = BLI_mempool_len(iter->pooliter.pool);
#endif
BLI_mempool_iternew(iter->pooliter.pool, &iter->pooliter);
}
@@ -438,7 +438,7 @@ void bmiter__elem_of_mesh_begin(struct BMIter__elem_of_mesh *iter)
void *bmiter__elem_of_mesh_step(struct BMIter__elem_of_mesh *iter)
{
#ifdef USE_IMMUTABLE_ASSERT
- BLI_assert(((BMIter *)iter)->count <= BLI_mempool_count(iter->pooliter.pool));
+ BLI_assert(((BMIter *)iter)->count <= BLI_mempool_len(iter->pooliter.pool));
#endif
return BLI_mempool_iterstep(&iter->pooliter);
}
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
index 1d16dbc1836..5ae72851c7e 100644
--- a/source/blender/bmesh/intern/bmesh_log.c
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -990,11 +990,11 @@ void BM_log_all_added(BMesh *bm, BMLog *log)
BMFace *f;
/* avoid unnecessary resizing on initialization */
- if (BLI_ghash_size(log->current_entry->added_verts) == 0) {
+ if (BLI_ghash_len(log->current_entry->added_verts) == 0) {
BLI_ghash_reserve(log->current_entry->added_verts, (uint)bm->totvert);
}
- if (BLI_ghash_size(log->current_entry->added_faces) == 0) {
+ if (BLI_ghash_len(log->current_entry->added_faces) == 0) {
BLI_ghash_reserve(log->current_entry->added_faces, (uint)bm->totface);
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index 67db51446df..9e03c28ba1b 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -521,21 +521,19 @@ void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (*
}
/**
- * Helpers for #BM_mesh_loop_normals_update and #BM_loops_calc_normals_vnos
+ * Helpers for #BM_mesh_loop_normals_update and #BM_loops_calc_normal_vcos
*/
static void bm_mesh_edges_sharp_tag(
- BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float split_angle,
- float (*r_lnos)[3])
+ BMesh *bm,
+ const float (*vnos)[3], const float (*fnos)[3], float (*r_lnos)[3],
+ const float split_angle, const bool do_sharp_edges_tag)
{
BMIter eiter;
BMEdge *e;
int i;
const bool check_angle = (split_angle < (float)M_PI);
-
- if (check_angle) {
- split_angle = cosf(split_angle);
- }
+ const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f;
{
char htype = BM_VERT | BM_LOOP;
@@ -560,7 +558,7 @@ static void bm_mesh_edges_sharp_tag(
if (check_angle) {
const float *no_a = fnos ? fnos[BM_elem_index_get(l_a->f)] : l_a->f->no;
const float *no_b = fnos ? fnos[BM_elem_index_get(l_b->f)] : l_b->f->no;
- is_angle_smooth = (dot_v3v3(no_a, no_b) >= split_angle);
+ is_angle_smooth = (dot_v3v3(no_a, no_b) >= split_angle_cos);
}
/* We only tag edges that are *really* smooth:
@@ -570,20 +568,28 @@ static void bm_mesh_edges_sharp_tag(
* and both its faces have compatible (non-flipped) normals,
* i.e. both loops on the same edge do not share the same vertex.
*/
- if (is_angle_smooth &&
- BM_elem_flag_test(e, BM_ELEM_SMOOTH) &&
+ if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) &&
BM_elem_flag_test(l_a->f, BM_ELEM_SMOOTH) &&
BM_elem_flag_test(l_b->f, BM_ELEM_SMOOTH) &&
l_a->v != l_b->v)
{
- const float *no;
- BM_elem_flag_enable(e, BM_ELEM_TAG);
-
- /* linked vertices might be fully smooth, copy their normals to loop ones. */
- no = vnos ? vnos[BM_elem_index_get(l_a->v)] : l_a->v->no;
- copy_v3_v3(r_lnos[BM_elem_index_get(l_a)], no);
- no = vnos ? vnos[BM_elem_index_get(l_b->v)] : l_b->v->no;
- copy_v3_v3(r_lnos[BM_elem_index_get(l_b)], no);
+ if (is_angle_smooth) {
+ const float *no;
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+
+ /* linked vertices might be fully smooth, copy their normals to loop ones. */
+ if (r_lnos) {
+ no = vnos ? vnos[BM_elem_index_get(l_a->v)] : l_a->v->no;
+ copy_v3_v3(r_lnos[BM_elem_index_get(l_a)], no);
+ no = vnos ? vnos[BM_elem_index_get(l_b->v)] : l_b->v->no;
+ copy_v3_v3(r_lnos[BM_elem_index_get(l_b)], no);
+ }
+ }
+ else if (do_sharp_edges_tag) {
+ /* Note that we do not care about the other sharp-edge cases (sharp poly, non-manifold edge, etc.),
+ * only tag edge as sharp when it is due to angle threashold. */
+ BM_elem_flag_disable(e, BM_ELEM_SMOOTH);
+ }
}
}
}
@@ -591,9 +597,11 @@ static void bm_mesh_edges_sharp_tag(
bm->elem_index_dirty &= ~BM_EDGE;
}
-/* Check whether gievn loop is part of an unknown-so-far cyclic smooth fan, or not.
- * Needed because cyclic smooth fans have no obvious 'entry point', and yet we need to walk them once, and only once. */
-static bool bm_mesh_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
+/**
+ * Check whether given loop is part of an unknown-so-far cyclic smooth fan, or not.
+ * Needed because cyclic smooth fans have no obvious 'entry point', and yet we need to walk them once, and only once.
+ */
+bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
{
BMLoop *lfan_pivot_next = l_curr;
BMEdge *e_next = l_curr->e;
@@ -659,7 +667,7 @@ static void bm_mesh_loops_calc_normals(
r_lnors_spacearr = &_lnors_spacearr;
}
if (r_lnors_spacearr) {
- BKE_lnor_spacearr_init(r_lnors_spacearr, bm->totloop);
+ BKE_lnor_spacearr_init(r_lnors_spacearr, bm->totloop, MLNOR_SPACEARR_BMLOOP_PTR);
edge_vectors = BLI_stack_new(sizeof(float[3]), __func__);
}
@@ -694,7 +702,7 @@ static void bm_mesh_loops_calc_normals(
* However, this would complicate the code, add more memory usage, and BM_vert_step_fan_loop()
* is quite cheap in term of CPU cycles, so really think it's not worth it. */
if (BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
- (BM_elem_flag_test(l_curr, BM_ELEM_TAG) || !bm_mesh_loop_check_cyclic_smooth_fan(l_curr)))
+ (BM_elem_flag_test(l_curr, BM_ELEM_TAG) || !BM_loop_check_cyclic_smooth_fan(l_curr)))
{
}
else if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
@@ -728,7 +736,7 @@ static void bm_mesh_loops_calc_normals(
BKE_lnor_space_define(lnor_space, r_lnos[l_curr_index], vec_curr, vec_prev, NULL);
/* We know there is only one loop in this space, no need to create a linklist in this case... */
- BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, l_curr_index, false);
+ BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, l_curr_index, l_curr, true);
if (has_clnors) {
short (*clnor)[2] = clnors_data ? &clnors_data[l_curr_index] :
@@ -847,7 +855,7 @@ static void bm_mesh_loops_calc_normals(
if (r_lnors_spacearr) {
/* Assign current lnor space to current 'vertex' loop. */
- BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, lfan_pivot_index, true);
+ BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, lfan_pivot_index, lfan_pivot, false);
if (e_next != e_org) {
/* We store here all edges-normalized vectors processed. */
BLI_stack_push(edge_vectors, vec_next);
@@ -1008,7 +1016,7 @@ void BM_loops_calc_normal_vcos(
if (use_split_normals) {
/* Tag smooth edges and set lnos from vnos when they might be completely smooth...
* When using custom loop normals, disable the angle feature! */
- bm_mesh_edges_sharp_tag(bm, vnos, fnos, has_clnors ? (float)M_PI : split_angle, r_lnos);
+ bm_mesh_edges_sharp_tag(bm, vnos, fnos, r_lnos, has_clnors ? (float)M_PI : split_angle, false);
/* Finish computing lnos by accumulating face normals in each fan of faces defined by sharp edges. */
bm_mesh_loops_calc_normals(bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset);
@@ -1019,7 +1027,22 @@ void BM_loops_calc_normal_vcos(
}
}
-static void UNUSED_FUNCTION(bm_mdisps_space_set)(Object *ob, BMesh *bm, int from, int to)
+/** Define sharp edges as needed to mimic 'autosmooth' from angle threshold.
+ *
+ * Used when defining an empty custom loop normals data layer, to keep same shading as with autosmooth!
+ */
+void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle)
+{
+ if (split_angle >= (float)M_PI) {
+ /* Nothing to do! */
+ return;
+ }
+
+ bm_mesh_edges_sharp_tag(bm, NULL, NULL, NULL, split_angle, true);
+}
+
+static void UNUSED_FUNCTION(bm_mdisps_space_set)(
+ Object *ob, BMesh *bm, int from, int to)
{
/* switch multires data out of tangent space */
if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index 01f11f6f942..10f024423aa 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -52,6 +52,11 @@ void BM_loops_calc_normal_vcos(
const bool use_split_normals, const float split_angle, float (*r_lnos)[3],
struct MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset);
+bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr);
+
+
+void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle);
+
void bmesh_edit_begin(BMesh *bm, const BMOpTypeFlag type_flag);
void bmesh_edit_end(BMesh *bm, const BMOpTypeFlag type_flag);
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c
index 6cc1f37db43..fd32119cb5f 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c
@@ -708,7 +708,7 @@ void BM_mesh_bm_to_me(
}
/* patch hook indices and vertex parents */
- if (ototvert > 0) {
+ if (params->calc_object_remap && (ototvert > 0)) {
Object *ob;
ModifierData *md;
BMVert **vertMap = NULL;
@@ -765,11 +765,7 @@ void BM_mesh_bm_to_me(
if (vertMap) MEM_freeN(vertMap);
}
- if (params->calc_tessface) {
- BKE_mesh_tessface_calc(me);
- }
-
- BKE_mesh_update_customdata_pointers(me, params->calc_tessface);
+ BKE_mesh_update_customdata_pointers(me, false);
{
BMEditSelection *selected;
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h
index 1974d364171..6e9d62349ea 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.h
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h
@@ -55,7 +55,8 @@ void BM_mesh_bm_from_me(
ATTR_NONNULL(1, 3);
struct BMeshToMeshParams {
- uint calc_tessface : 1;
+ /** Update object hook indices & vertex parents. */
+ uint calc_object_remap : 1;
int64_t cd_mask_extra;
};
void BM_mesh_bm_to_me(
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index 1cd51528e06..4290f94bba1 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -65,7 +65,7 @@
bool BM_vert_dissolve(BMesh *bm, BMVert *v)
{
/* logic for 3 or more is identical */
- const int len = BM_vert_edge_count_ex(v, 3);
+ const int len = BM_vert_edge_count_at_most(v, 3);
if (len == 1) {
BM_vert_kill(bm, v); /* will kill edges too */
@@ -482,8 +482,8 @@ BMEdge *BM_vert_collapse_faces(
BLI_array_append(faces, f);
}
- if (BLI_array_count(faces) >= 2) {
- BMFace *f2 = BM_faces_join(bm, faces, BLI_array_count(faces), true);
+ if (BLI_array_len(faces) >= 2) {
+ BMFace *f2 = BM_faces_join(bm, faces, BLI_array_len(faces), true);
if (f2) {
BMLoop *l_a, *l_b;
@@ -499,7 +499,7 @@ BMEdge *BM_vert_collapse_faces(
}
}
- BLI_assert(BLI_array_count(faces) < 8);
+ BLI_assert(BLI_array_len(faces) < 8);
BLI_array_free(faces);
}
@@ -608,7 +608,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
} while (l != e->l);
/* flag existing faces so we can differentiate oldfaces from new faces */
- for (i = 0; i < BLI_array_count(oldfaces); i++) {
+ for (i = 0; i < BLI_array_len(oldfaces); i++) {
BM_ELEM_API_FLAG_ENABLE(oldfaces[i], _FLAG_OVERLAP);
oldfaces[i] = BM_face_copy(bm, bm, oldfaces[i], true, true);
BM_ELEM_API_FLAG_DISABLE(oldfaces[i], _FLAG_OVERLAP);
@@ -639,7 +639,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
int i, j;
/* interpolate new/changed loop data from copied old faces */
- for (i = 0; i < BLI_array_count(oldfaces); i++) {
+ for (i = 0; i < BLI_array_len(oldfaces); i++) {
float f_center_old[3];
BM_face_calc_center_mean(oldfaces[i], f_center_old);
@@ -671,7 +671,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
}
/* destroy the old faces */
- for (i = 0; i < BLI_array_count(oldfaces); i++) {
+ for (i = 0; i < BLI_array_len(oldfaces); i++) {
BM_face_verts_kill(bm, oldfaces[i]);
}
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index ddc2b26417c..37a4fb5c29c 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -843,7 +843,6 @@ static BMOpDefine bmo_bmesh_to_mesh_def = {
{"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}},
/* pointer to an object structure */
{"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}},
- {"skip_tessface", BMO_OP_SLOT_BOOL}, /* don't calculate mfaces */
{{'\0'}},
},
{{{'\0'}}}, /* no output */
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index 0f672a9ff2a..f814767a200 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -673,7 +673,7 @@ int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
- return BLI_ghash_size(slot->data.ghash);
+ return BLI_ghash_len(slot->data.ghash);
}
/* inserts a key/value mapping into a mapping slot. note that it copies the
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 66fcd739839..bcb940f8b96 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -36,8 +36,8 @@
#include "BLI_alloca.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
-#include "BLI_polyfill2d.h"
-#include "BLI_polyfill2d_beautify.h"
+#include "BLI_polyfill_2d.h"
+#include "BLI_polyfill_2d_beautify.h"
#include "BLI_linklist.h"
#include "BLI_edgehash.h"
#include "BLI_heap.h"
@@ -1426,6 +1426,17 @@ void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptri
(l_ptr_a[2] = l_ptr_b[1] = l = l->next);
( l_ptr_b[2] = l->next);
#endif
+
+ if (UNLIKELY(is_quad_flip_v3_first_third_fast(
+ l_ptr_a[0]->v->co,
+ l_ptr_a[1]->v->co,
+ l_ptr_a[2]->v->co,
+ l_ptr_b[2]->v->co)))
+ {
+ /* flip out of degenerate 0-2 state. */
+ l_ptr_a[2] = l_ptr_b[2];
+ l_ptr_b[0] = l_ptr_a[1];
+ }
}
#endif /* USE_TESSFACE_SPEEDUP */
diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
index 41775bdf2d0..85dfd3f58e2 100644
--- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
+++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
@@ -665,7 +665,7 @@ bool BM_face_split_edgenet(
BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_VISIT);
} while ((l_iter = l_iter->next) != l_first);
- if (BLI_array_count(face_arr)) {
+ if (BLI_array_len(face_arr)) {
bmesh_face_swap_data(f, face_arr[0]);
BM_face_kill(bm, face_arr[0]);
face_arr[0] = f;
@@ -674,13 +674,13 @@ bool BM_face_split_edgenet(
BM_ELEM_API_FLAG_DISABLE(f, FACE_NET);
}
- for (i = 0; i < BLI_array_count(face_arr); i++) {
+ for (i = 0; i < BLI_array_len(face_arr); i++) {
BM_ELEM_API_FLAG_DISABLE(face_arr[i], FACE_NET);
}
if (r_face_arr) {
*r_face_arr = face_arr;
- *r_face_arr_len = BLI_array_count(face_arr);
+ *r_face_arr_len = BLI_array_len(face_arr);
}
else {
if (face_arr) {
@@ -860,7 +860,7 @@ static void bvhtree_test_edges_isect_2d_ray_cb(
/**
* Store values for:
* - #bm_face_split_edgenet_find_connection
- * - #test_edges_isect_2d
+ * - #test_edges_isect_2d_vert
* ... which don't change each call.
*/
struct EdgeGroup_FindConnection_Args {
diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h
index 4dcf97e3f35..daee22ffe76 100644
--- a/source/blender/bmesh/intern/bmesh_private.h
+++ b/source/blender/bmesh/intern/bmesh_private.h
@@ -55,7 +55,7 @@ int bmesh_elem_check(void *element, const char htype);
#endif
int bmesh_radial_length(const BMLoop *l);
-int bmesh_disk_count_ex(const BMVert *v, const int count_max);
+int bmesh_disk_count_at_most(const BMVert *v, const int count_max);
int bmesh_disk_count(const BMVert *v);
/**
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 32f726df01d..ab2f017d103 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -799,9 +799,9 @@ int BM_vert_edge_count(const BMVert *v)
return bmesh_disk_count(v);
}
-int BM_vert_edge_count_ex(const BMVert *v, const int count_max)
+int BM_vert_edge_count_at_most(const BMVert *v, const int count_max)
{
- return bmesh_disk_count_ex(v, count_max);
+ return bmesh_disk_count_at_most(v, count_max);
}
int BM_vert_edge_count_nonwire(const BMVert *v)
@@ -835,7 +835,7 @@ int BM_edge_face_count(const BMEdge *e)
return count;
}
-int BM_edge_face_count_ex(const BMEdge *e, const int count_max)
+int BM_edge_face_count_at_most(const BMEdge *e, const int count_max)
{
int count = 0;
@@ -863,9 +863,9 @@ int BM_vert_face_count(const BMVert *v)
return bmesh_disk_facevert_count(v);
}
-int BM_vert_face_count_ex(const BMVert *v, int count_max)
+int BM_vert_face_count_at_most(const BMVert *v, int count_max)
{
- return bmesh_disk_facevert_count_ex(v, count_max);
+ return bmesh_disk_facevert_count_at_most(v, count_max);
}
/**
@@ -1044,7 +1044,7 @@ static int bm_loop_region_count__clear(BMLoop *l)
/**
* The number of loops connected to this loop (not including disconnected regions).
*/
-int BM_loop_region_loops_count_ex(BMLoop *l, int *r_loop_total)
+int BM_loop_region_loops_count_at_most(BMLoop *l, int *r_loop_total)
{
const int count = bm_loop_region_count__recursive(l->e, l->v);
const int count_total = bm_loop_region_count__clear(l);
@@ -1059,7 +1059,7 @@ int BM_loop_region_loops_count_ex(BMLoop *l, int *r_loop_total)
int BM_loop_region_loops_count(BMLoop *l)
{
- return BM_loop_region_loops_count_ex(l, NULL);
+ return BM_loop_region_loops_count_at_most(l, NULL);
}
/**
@@ -1071,7 +1071,7 @@ bool BM_vert_is_manifold_region(const BMVert *v)
BMLoop *l_first = BM_vert_find_first_loop((BMVert *)v);
if (l_first) {
int count, count_total;
- count = BM_loop_region_loops_count_ex(l_first, &count_total);
+ count = BM_loop_region_loops_count_at_most(l_first, &count_total);
return (count == count_total);
}
return true;
@@ -1526,9 +1526,9 @@ float BM_loop_calc_face_angle(const BMLoop *l)
*
* Calculate the normal at this loop corner or fallback to the face normal on straight lines.
*
- * \param l The loop to calculate the normal at
- * \param epsilon: Value to avoid numeric errors (1e-5f works well).
- * \param r_normal Resulting normal
+ * \param l: The loop to calculate the normal at.
+ * \param epsilon_sq: Value to avoid numeric errors (1e-5f works well).
+ * \param r_normal: Resulting normal.
*/
float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, float r_normal[3])
{
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index c9fce96c798..e602c63da94 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -70,17 +70,17 @@ BMFace *BM_edge_pair_share_face_by_len(
const bool allow_adjacent) ATTR_NONNULL();
int BM_vert_edge_count_nonwire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-#define BM_vert_edge_count_is_equal(v, n) (BM_vert_edge_count_ex(v, (n) + 1) == n)
-#define BM_vert_edge_count_is_over(v, n) (BM_vert_edge_count_ex(v, (n) + 1) == (n) + 1)
-int BM_vert_edge_count_ex(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+#define BM_vert_edge_count_is_equal(v, n) (BM_vert_edge_count_at_most(v, (n) + 1) == n)
+#define BM_vert_edge_count_is_over(v, n) (BM_vert_edge_count_at_most(v, (n) + 1) == (n) + 1)
+int BM_vert_edge_count_at_most(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int BM_vert_edge_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-#define BM_edge_face_count_is_equal(e, n) (BM_edge_face_count_ex(e, (n) + 1) == n)
-#define BM_edge_face_count_is_over(e, n) (BM_edge_face_count_ex(e, (n) + 1) == (n) + 1)
-int BM_edge_face_count_ex(const BMEdge *e, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+#define BM_edge_face_count_is_equal(e, n) (BM_edge_face_count_at_most(e, (n) + 1) == n)
+#define BM_edge_face_count_is_over(e, n) (BM_edge_face_count_at_most(e, (n) + 1) == (n) + 1)
+int BM_edge_face_count_at_most(const BMEdge *e, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int BM_edge_face_count(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-#define BM_vert_face_count_is_equal(v, n) (BM_vert_face_count_ex(v, (n) + 1) == n)
-#define BM_vert_face_count_is_over(v, n) (BM_vert_face_count_ex(v, (n) + 1) == (n) + 1)
-int BM_vert_face_count_ex(const BMVert *v, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+#define BM_vert_face_count_is_equal(v, n) (BM_vert_face_count_at_most(v, (n) + 1) == n)
+#define BM_vert_face_count_is_over(v, n) (BM_vert_face_count_at_most(v, (n) + 1) == (n) + 1)
+int BM_vert_face_count_at_most(const BMVert *v, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int BM_vert_face_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -103,7 +103,7 @@ bool BM_edge_is_contiguous_loop_cd(
const int cd_loop_type, const int cd_loop_offset)
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int BM_loop_region_loops_count_ex(BMLoop *l, int *r_loop_total) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+int BM_loop_region_loops_count_at_most(BMLoop *l, int *r_loop_total) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
int BM_loop_region_loops_count(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
bool BM_loop_is_convex(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c
index 8e484841568..8aa9502c0f7 100644
--- a/source/blender/bmesh/intern/bmesh_structure.c
+++ b/source/blender/bmesh/intern/bmesh_structure.c
@@ -244,7 +244,7 @@ int bmesh_disk_count(const BMVert *v)
return count;
}
-int bmesh_disk_count_ex(const BMVert *v, const int count_max)
+int bmesh_disk_count_at_most(const BMVert *v, const int count_max)
{
int count = 0;
if (v->e) {
@@ -267,7 +267,7 @@ bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v)
if (!BM_vert_in_edge(e, v)) {
return false;
}
- if (len == 0 || bmesh_disk_count_ex(v, len + 1) != len) {
+ if (len == 0 || bmesh_disk_count_at_most(v, len + 1) != len) {
return false;
}
@@ -307,7 +307,7 @@ int bmesh_disk_facevert_count(const BMVert *v)
return count;
}
-int bmesh_disk_facevert_count_ex(const BMVert *v, const int count_max)
+int bmesh_disk_facevert_count_at_most(const BMVert *v, const int count_max)
{
/* is there an edge on this vert at all */
int count = 0;
@@ -318,7 +318,7 @@ int bmesh_disk_facevert_count_ex(const BMVert *v, const int count_max)
e_first = e_iter = v->e;
do {
if (e_iter->l) {
- count += bmesh_radial_facevert_count_ex(e_iter->l, v, count_max - count);
+ count += bmesh_radial_facevert_count_at_most(e_iter->l, v, count_max - count);
if (count == count_max) {
break;
}
@@ -560,7 +560,7 @@ int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v)
return count;
}
-int bmesh_radial_facevert_count_ex(const BMLoop *l, const BMVert *v, const int count_max)
+int bmesh_radial_facevert_count_at_most(const BMLoop *l, const BMVert *v, const int count_max)
{
const BMLoop *l_iter;
int count = 0;
diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h
index 0efb25da37c..974b276f8b3 100644
--- a/source/blender/bmesh/intern/bmesh_structure.h
+++ b/source/blender/bmesh/intern/bmesh_structure.h
@@ -49,7 +49,7 @@ BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v) A
BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int bmesh_disk_facevert_count_ex(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int bmesh_disk_facevert_count_at_most(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int bmesh_disk_facevert_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMLoop *bmesh_disk_faceloop_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -63,7 +63,7 @@ void bmesh_radial_loop_unlink(BMLoop *l) ATTR_NONNULL();
* bmesh_radial_loop_next(BMLoop *l) / prev.
* just use member access l->radial_next, l->radial_prev now */
-int bmesh_radial_facevert_count_ex(const BMLoop *l, const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int bmesh_radial_facevert_count_at_most(const BMLoop *l, const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool bmesh_radial_facevert_check(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
diff --git a/source/blender/bmesh/operators/bmo_connect_concave.c b/source/blender/bmesh/operators/bmo_connect_concave.c
index 80774323d31..d1811ac6a83 100644
--- a/source/blender/bmesh/operators/bmo_connect_concave.c
+++ b/source/blender/bmesh/operators/bmo_connect_concave.c
@@ -39,8 +39,8 @@
#include "BLI_alloca.h"
#include "BLI_memarena.h"
#include "BLI_heap.h"
-#include "BLI_polyfill2d.h"
-#include "BLI_polyfill2d_beautify.h"
+#include "BLI_polyfill_2d.h"
+#include "BLI_polyfill_2d_beautify.h"
#include "BLI_linklist.h"
#include "bmesh.h"
diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c
index 60fd9808fcb..b9e5cd927c3 100644
--- a/source/blender/bmesh/operators/bmo_connect_pair.c
+++ b/source/blender/bmesh/operators/bmo_connect_pair.c
@@ -662,11 +662,11 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
while (!BLI_heap_is_empty(pc.states)) {
#ifdef DEBUG_PRINT
- printf("\n%s: stepping %u\n", __func__, BLI_heap_size(pc.states));
+ printf("\n%s: stepping %u\n", __func__, BLI_heap_len(pc.states));
#endif
while (!BLI_heap_is_empty(pc.states)) {
- PathLinkState *state = BLI_heap_popmin(pc.states);
+ PathLinkState *state = BLI_heap_pop_min(pc.states);
/* either we insert this into 'pc.states' or its freed */
bool continue_search;
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c
index 2df8e73c2b8..816d2e8d009 100644
--- a/source/blender/bmesh/operators/bmo_dissolve.c
+++ b/source/blender/bmesh/operators/bmo_dissolve.c
@@ -166,7 +166,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
continue;
}
- BLI_array_empty(faces);
+ BLI_array_clear(faces);
faces = NULL; /* forces different allocatio */
BMW_init(&regwalker, bm, BMW_ISLAND_MANIFOLD,
@@ -179,7 +179,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
}
BMW_end(&regwalker);
- for (i = 0; i < BLI_array_count(faces); i++) {
+ for (i = 0; i < BLI_array_len(faces); i++) {
f_iter = faces[i];
BMO_face_flag_disable(bm, f_iter, FACE_TAG);
BMO_face_flag_enable(bm, f_iter, FACE_ORIG);
@@ -198,7 +198,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
/* track how many faces we should end up with */
int totface_target = bm->totface;
- for (i = 0; i < BLI_array_count(regions); i++) {
+ for (i = 0; i < BLI_array_len(regions); i++) {
BMFace *f_new;
int tot = 0;
@@ -259,7 +259,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
cleanup:
/* free/cleanup */
- for (i = 0; i < BLI_array_count(regions); i++) {
+ for (i = 0; i < BLI_array_len(regions); i++) {
if (regions[i]) MEM_freeN(regions[i]);
}
diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c
index 64b092da5c8..931ac684b07 100644
--- a/source/blender/bmesh/operators/bmo_edgenet.c
+++ b/source/blender/bmesh/operators/bmo_edgenet.c
@@ -179,22 +179,22 @@ void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op)
if (!count) {
edges1 = edges;
- BLI_array_count_set(edges1, BLI_array_count(edges));
+ BLI_array_len_set(edges1, BLI_array_len(edges));
}
else {
edges2 = edges;
- BLI_array_count_set(edges2, BLI_array_count(edges));
+ BLI_array_len_set(edges2, BLI_array_len(edges));
}
- BLI_array_empty(edges);
+ BLI_array_clear(edges);
count++;
}
- if (edges1 && BLI_array_count(edges1) > 2 &&
- BM_edge_share_vert_check(edges1[0], edges1[BLI_array_count(edges1) - 1]))
+ if (edges1 && BLI_array_len(edges1) > 2 &&
+ BM_edge_share_vert_check(edges1[0], edges1[BLI_array_len(edges1) - 1]))
{
- if (edges2 && BLI_array_count(edges2) > 2 &&
- BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1]))
+ if (edges2 && BLI_array_len(edges2) > 2 &&
+ BM_edge_share_vert_check(edges2[0], edges2[BLI_array_len(edges2) - 1]))
{
BLI_array_free(edges1);
BLI_array_free(edges2);
@@ -206,8 +206,8 @@ void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op)
}
}
- if (edges2 && BLI_array_count(edges2) > 2 &&
- BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1]))
+ if (edges2 && BLI_array_len(edges2) > 2 &&
+ BM_edge_share_vert_check(edges2[0], edges2[BLI_array_len(edges2) - 1]))
{
edges2 = NULL;
}
@@ -218,23 +218,23 @@ void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op)
float dvec1[3];
float dvec2[3];
- if (BLI_array_count(edges1) == 1) {
+ if (BLI_array_len(edges1) == 1) {
v1 = edges1[0]->v1;
v2 = edges1[0]->v2;
}
else {
v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1;
- i = BLI_array_count(edges1) - 1;
+ i = BLI_array_len(edges1) - 1;
v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1;
}
- if (BLI_array_count(edges2) == 1) {
+ if (BLI_array_len(edges2) == 1) {
v3 = edges2[0]->v1;
v4 = edges2[0]->v2;
}
else {
v3 = BM_vert_in_edge(edges2[1], edges2[0]->v1) ? edges2[0]->v2 : edges2[0]->v1;
- i = BLI_array_count(edges2) - 1;
+ i = BLI_array_len(edges2) - 1;
v4 = BM_vert_in_edge(edges2[i - 1], edges2[i]->v1) ? edges2[i]->v2 : edges2[i]->v1;
}
@@ -265,9 +265,9 @@ void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op)
else if (edges1) {
BMVert *v1, *v2;
- if (BLI_array_count(edges1) > 1) {
+ if (BLI_array_len(edges1) > 1) {
v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1;
- i = BLI_array_count(edges1) - 1;
+ i = BLI_array_len(edges1) - 1;
v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1;
e = BM_edge_create(bm, v1, v2, NULL, BM_CREATE_NO_DOUBLE);
BMO_edge_flag_enable(bm, e, ELE_NEW);
diff --git a/source/blender/bmesh/operators/bmo_face_island.c b/source/blender/bmesh/operators/bmo_face_island.c
index 77b28f2f29c..e52052a28d3 100644
--- a/source/blender/bmesh/operators/bmo_face_island.c
+++ b/source/blender/bmesh/operators/bmo_face_island.c
@@ -99,7 +99,7 @@ void bmo_face_island_boundary_exec(BMesh *bm, BMOperator *op)
{
BMOpSlot *slot = BMO_slot_get(op->slots_out, "boundary");
- BMO_slot_buffer_from_array(op, slot, (BMHeader **)boundary, BLI_array_count(boundary));
+ BMO_slot_buffer_from_array(op, slot, (BMHeader **)boundary, BLI_array_len(boundary));
BLI_array_free(boundary);
}
diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c
index 81ec2860cf7..d52cb00e172 100644
--- a/source/blender/bmesh/operators/bmo_hull.c
+++ b/source/blender/bmesh/operators/bmo_hull.c
@@ -521,7 +521,7 @@ static void hull_from_bullet(
int j;
/* Get face vertex indices */
- BLI_array_empty(fvi);
+ BLI_array_clear(fvi);
BLI_array_grow_items(fvi, len);
plConvexHullGetFaceVertices(hull, i, fvi);
diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c
index 69198ff35ab..b1053e6d8c2 100644
--- a/source/blender/bmesh/operators/bmo_join_triangles.c
+++ b/source/blender/bmesh/operators/bmo_join_triangles.c
@@ -270,7 +270,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
BMFace *f;
BMEdge *e;
/* data: edge-to-join, sort_value: error weight */
- struct SortPointerByFloat *jedges;
+ struct SortPtrByFloat *jedges;
unsigned i, totedge;
uint totedge_tag = 0;
diff --git a/source/blender/bmesh/operators/bmo_mesh_conv.c b/source/blender/bmesh/operators/bmo_mesh_conv.c
index 0eb9bf90ca8..7311ed5ce64 100644
--- a/source/blender/bmesh/operators/bmo_mesh_conv.c
+++ b/source/blender/bmesh/operators/bmo_mesh_conv.c
@@ -62,15 +62,18 @@ void bmo_object_load_bmesh_exec(BMesh *bm, BMOperator *op)
Mesh *me = ob->data;
BMO_op_callf(bm, op->flag,
- "bmesh_to_mesh mesh=%p object=%p skip_tessface=%b",
- me, ob, true);
+ "bmesh_to_mesh mesh=%p object=%p",
+ me, ob);
}
void bmo_bmesh_to_mesh_exec(BMesh *bm, BMOperator *op)
{
Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh");
/* Object *ob = BMO_slot_ptr_get(op, "object"); */
- const bool dotess = !BMO_slot_bool_get(op->slots_in, "skip_tessface");
- BM_mesh_bm_to_me(bm, me, (&(struct BMeshToMeshParams){ .calc_tessface = dotess, }));
+ BM_mesh_bm_to_me(
+ bm, me,
+ (&(struct BMeshToMeshParams){
+ .calc_object_remap = true,
+ }));
}
diff --git a/source/blender/bmesh/operators/bmo_rotate_edges.c b/source/blender/bmesh/operators/bmo_rotate_edges.c
index 9832fdb57d3..75e31c68dae 100644
--- a/source/blender/bmesh/operators/bmo_rotate_edges.c
+++ b/source/blender/bmesh/operators/bmo_rotate_edges.c
@@ -180,7 +180,7 @@ static void bm_rotate_edges_shared(
const int edges_len_rotate_prev = edges_len_rotate;
while (!BLI_heap_is_empty(heap)) {
- BMEdge *e_best = BLI_heap_popmin(heap);
+ BMEdge *e_best = BLI_heap_pop_min(heap);
eheap_table[BM_elem_index_get(e_best)] = NULL;
/* No problem if this fails, re-evaluate if faces connected to this edge are touched. */
diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c
index 894129b4a33..8f998797a16 100644
--- a/source/blender/bmesh/operators/bmo_subdivide.c
+++ b/source/blender/bmesh/operators/bmo_subdivide.c
@@ -1011,8 +1011,8 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
/* figure out which pattern to use */
- BLI_array_empty(edges);
- BLI_array_empty(verts);
+ BLI_array_clear(edges);
+ BLI_array_clear(verts);
BLI_array_grow_items(edges, face->len);
BLI_array_grow_items(verts, face->len);
@@ -1140,7 +1140,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
face = fd->face;
/* figure out which pattern to use */
- BLI_array_empty(verts);
+ BLI_array_clear(verts);
pat = fd->pat;
@@ -1148,8 +1148,8 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
int vlen;
/* ok, no pattern. we still may be able to do something */
- BLI_array_empty(loops);
- BLI_array_empty(loops_split);
+ BLI_array_clear(loops);
+ BLI_array_clear(loops_split);
/* for case of two edges, connecting them shouldn't be too hard */
BLI_array_grow_items(loops, face->len);
@@ -1157,7 +1157,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
loops[a] = l;
}
- vlen = BLI_array_count(loops);
+ vlen = BLI_array_len(loops);
/* find the boundary of one of the split edges */
for (a = 1; a < vlen; a++) {
@@ -1236,9 +1236,9 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
* - concave corner of an ngon.
* - 2 edges being used in 2+ ngons.
*/
-// BM_face_splits_check_legal(bm, face, loops_split, BLI_array_count(loops_split));
+// BM_face_splits_check_legal(bm, face, loops_split, BLI_array_len(loops_split));
- for (j = 0; j < BLI_array_count(loops_split); j++) {
+ for (j = 0; j < BLI_array_len(loops_split); j++) {
if (loops_split[j][0]) {
BMFace *f_new;
BLI_assert(BM_edge_exists(loops_split[j][0]->v, loops_split[j][1]->v) == NULL);
diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
index adcc0c71629..e6881f6d8b1 100644
--- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c
+++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
@@ -269,7 +269,7 @@ static GSet *bm_edgering_pair_calc(BMesh *bm, ListBase *eloops_rim)
BLI_ghash_free(vert_eloop_gh, NULL, NULL);
- if (BLI_gset_size(eloop_pair_gs) == 0) {
+ if (BLI_gset_len(eloop_pair_gs) == 0) {
BLI_gset_free(eloop_pair_gs, NULL);
eloop_pair_gs = NULL;
}
@@ -1193,7 +1193,7 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op)
goto cleanup;
}
- lpair_arr = BLI_array_alloca(lpair_arr, BLI_gset_size(eloop_pairs_gs));
+ lpair_arr = BLI_array_alloca(lpair_arr, BLI_gset_len(eloop_pairs_gs));
/* first cache pairs */
GSET_ITER_INDEX (gs_iter, eloop_pairs_gs, i) {
diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c
index 4e8bace59e0..2cdc2646649 100644
--- a/source/blender/bmesh/operators/bmo_triangulate.c
+++ b/source/blender/bmesh/operators/bmo_triangulate.c
@@ -106,7 +106,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
/* sf_edge = */ BLI_scanfill_edge_add(&sf_ctx, UNPACK2(sf_verts));
/* sf_edge->tmp.p = e; */ /* UNUSED */
}
- nors_tot = BLI_ghash_size(sf_vert_map);
+ nors_tot = BLI_ghash_len(sf_vert_map);
BLI_ghash_free(sf_vert_map, NULL, NULL);
diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c
index 6e6242fc9f9..d3972363bb4 100644
--- a/source/blender/bmesh/tools/bmesh_beautify.c
+++ b/source/blender/bmesh/tools/bmesh_beautify.c
@@ -37,7 +37,7 @@
#include "BLI_math.h"
#include "BLI_heap.h"
-#include "BLI_polyfill2d_beautify.h"
+#include "BLI_polyfill_2d_beautify.h"
#include "MEM_guardedalloc.h"
@@ -392,7 +392,7 @@ void BM_mesh_beautify_fill(
bm->elem_index_dirty |= BM_EDGE;
while (BLI_heap_is_empty(eheap) == false) {
- BMEdge *e = BLI_heap_popmin(eheap);
+ BMEdge *e = BLI_heap_pop_min(eheap);
i = BM_elem_index_get(e);
eheap_table[i] = NULL;
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 18b2b4db2bf..457e74ce1aa 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -44,6 +44,8 @@
#include "BKE_customdata.h"
#include "BKE_deform.h"
+#include "eigen_capi.h"
+
#include "bmesh.h"
#include "bmesh_bevel.h" /* own include */
@@ -58,6 +60,7 @@
#define BEVEL_SMALL_ANG DEG2RADF(10.0f)
#define BEVEL_MAX_ADJUST_PCT 10.0f
#define BEVEL_MAX_AUTO_ADJUST_PCT 300.0f
+#define BEVEL_MATCH_SPEC_WEIGHT 0.2
/* happens far too often, uncomment for development */
// #define BEVEL_ASSERT_PROJECT
@@ -139,10 +142,14 @@ typedef struct BoundVert {
NewVert nv;
EdgeHalf *efirst; /* first of edges attached here: in CCW order */
EdgeHalf *elast;
+ EdgeHalf *eon; /* the "edge between" that this is on, in offset_on_edge_between case */
EdgeHalf *ebev; /* beveled edge whose left side is attached here, if any */
int index; /* used for vmesh indexing */
+ float sinratio; /* when eon set, ratio of sines of angles to eon edge */
+ struct BoundVert *adjchain; /* adjustment chain or cycle link pointer */
Profile profile; /* edge profile between this and next BoundVert */
bool any_seam; /* are any of the edges attached here seams? */
+ bool visited; /* used during delta adjust pass */
// int _pad;
} BoundVert;
@@ -192,6 +199,7 @@ typedef struct BevelParams {
bool use_weights; /* bevel amount affected by weights on edges or verts */
bool loop_slide; /* should bevel prefer to slide along edges rather than keep widths spec? */
bool limit_offset; /* should offsets be limited by collisions? */
+ bool offset_adjust; /* should offsets be adjusted to try to get even widths? */
const struct MDeformVert *dvert; /* vertex group array, maybe set if vertex_only */
int vertex_group; /* vertex group index, maybe set if vertex_only */
int mat_nr; /* if >= 0, material number for bevel; else material comes from adjacent faces */
@@ -207,6 +215,7 @@ static int bev_debug_flags = 0;
#define DEBUG_OLD_PROJ_TO_PERP_PLANE (bev_debug_flags & 2)
#define DEBUG_OLD_FLAT_MID (bev_debug_flags & 4)
+
/* this flag values will get set on geom we want to return in 'out' slots for edges and verts */
#define EDGE_OUT 4
#define VERT_OUT 8
@@ -260,6 +269,9 @@ static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float
vm->boundstart->prev = ans;
}
ans->profile.super_r = PRO_LINE_R;
+ ans->adjchain = NULL;
+ ans->sinratio = 1.0f;
+ ans->visited = false;
vm->count++;
return ans;
}
@@ -342,52 +354,6 @@ static EdgeHalf *find_other_end_edge_half(BevelParams *bp, EdgeHalf *e, BevVert
return NULL;
}
-static bool other_edge_half_visited(BevelParams *bp, EdgeHalf *e)
-{
- BevVert *bvo;
-
- bvo = find_bevvert(bp, e->is_rev ? e->e->v1 : e->e->v2);
- if (bvo)
- return bvo->visited;
- else
- return false;
-}
-
-static bool edge_half_offset_changed(EdgeHalf *e)
-{
- return e->offset_l != e->offset_l_spec ||
- e->offset_r != e->offset_r_spec;
-}
-
-static float adjusted_rel_change(float val, float spec)
-{
- float relchg;
-
- relchg = 0.0f;
- if (val != spec) {
- if (spec == 0)
- relchg = 1000.0f; /* arbitrary large value */
- else
- relchg = fabsf((val - spec) / spec);
- }
- return relchg;
-}
-
-static float max_edge_half_offset_rel_change(BevVert *bv)
-{
- int i;
- float max_rel_change;
- EdgeHalf *e;
-
- max_rel_change = 0.0f;
- for (i = 0; i < bv->edgecount; i++) {
- e = &bv->edges[i];
- max_rel_change = max_ff(max_rel_change, adjusted_rel_change(e->offset_l, e->offset_l_spec));
- max_rel_change = max_ff(max_rel_change, adjusted_rel_change(e->offset_r, e->offset_r_spec));
- }
- return max_rel_change;
-}
-
/* Return the next EdgeHalf after from_e that is beveled.
* If from_e is NULL, find the first beveled edge. */
static EdgeHalf *next_bev(BevVert *bv, EdgeHalf *from_e)
@@ -818,10 +784,6 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e
copy_v3_v3(off1a, v->co);
d = max_ff(e1->offset_r, e2->offset_l);
madd_v3_v3fl(off1a, norm_perp1, d);
- if (e1->offset_r != d)
- e1->offset_r = d;
- else if (e2->offset_l != d)
- e2->offset_l = d;
copy_v3_v3(meetco, off1a);
}
else if (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_ANG) {
@@ -830,10 +792,6 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e
* common line, at offset distance from v. */
d = max_ff(e1->offset_r, e2->offset_l);
slide_dist(e2, v, d, meetco);
- if (e1->offset_r != d)
- e1->offset_r = d;
- else if (e2->offset_l != d)
- e2->offset_l = d;
}
else {
/* Get normal to plane where meet point should be,
@@ -871,7 +829,6 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e
negate_v3(norm_v2);
}
-
/* get vectors perp to each edge, perp to norm_v, and pointing into face */
cross_v3_v3v3(norm_perp1, dir1, norm_v1);
cross_v3_v3v3(norm_perp2, dir2, norm_v2);
@@ -891,9 +848,6 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e
if (isect_kind == 0) {
/* lines are collinear: we already tested for this, but this used a different epsilon */
copy_v3_v3(meetco, off1a); /* just to do something */
- d = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co);
- if (fabsf(d - e2->offset_l) > BEVEL_EPSILON)
- e2->offset_l = d;
}
else {
/* The lines intersect, but is it at a reasonable place?
@@ -903,11 +857,9 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e
* or if the offset amount is > the edge length*/
if (e1->offset_r == 0.0f && is_outside_edge(e1, meetco, &closer_v)) {
copy_v3_v3(meetco, closer_v->co);
- e2->offset_l = len_v3v3(meetco, v->co);
}
if (e2->offset_l == 0.0f && is_outside_edge(e2, meetco, &closer_v)) {
copy_v3_v3(meetco, closer_v->co);
- e1->offset_r = len_v3v3(meetco, v->co);
}
if (edges_between && e1->offset_r > 0.0f && e2->offset_l > 0.0f) {
/* Try to drop meetco to a face between e1 and e2 */
@@ -926,8 +878,6 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e
break;
}
}
- e1->offset_r = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e1->e, v)->co);
- e2->offset_l = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co);
}
}
}
@@ -994,40 +944,27 @@ static bool good_offset_on_edge_between(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *em
/* Calculate the best place for a meeting point for the offsets from edges e1 and e2
* on the in-between edge emid. Viewed from the vertex normal side, the CCW
* order of these edges is e1, emid, e2.
- * The offsets probably do not meet at a common point on emid, so need to pick
- * one that causes the least problems. If the other end of one of e1 or e2 has been visited
- * already, prefer to keep the offset the same on this end.
- * Otherwise, pick a point between the two intersection points on emid that minimizes
- * the sum of squares of errors from desired offset. */
-static void offset_on_edge_between(
- BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid,
- BMVert *v, float meetco[3])
+ * Return true if we placed meetco as compromise between where two edges met.
+ * If we did, put ration of sines of angles in *r_sinratio too */
+static bool offset_on_edge_between(
+ EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid,
+ BMVert *v, float meetco[3], float *r_sinratio)
{
- float d, ang1, ang2, sina1, sina2, lambda;
+ float ang1, ang2;
float meet1[3], meet2[3];
- bool visited1, visited2, ok1, ok2;
+ bool ok1, ok2;
+ bool retval = false;
BLI_assert(e1->is_bev && e2->is_bev && !emid->is_bev);
- visited1 = other_edge_half_visited(bp, e1);
- visited2 = other_edge_half_visited(bp, e2);
-
ok1 = offset_meet_edge(e1, emid, v, meet1, &ang1);
ok2 = offset_meet_edge(emid, e2, v, meet2, &ang2);
if (ok1 && ok2) {
- if (visited1 && !visited2) {
- copy_v3_v3(meetco, meet1);
- }
- else if (!visited1 && visited2) {
- copy_v3_v3(meetco, meet2);
- }
- else {
- /* find best compromise meet point */
- sina1 = sinf(ang1);
- sina2 = sinf(ang2);
- lambda = sina2 * sina2 / (sina1 * sina1 + sina2 * sina2);
- interp_v3_v3v3(meetco, meet1, meet2, lambda);
- }
+ mid_v3_v3v3(meetco, meet1, meet2);
+ if (r_sinratio)
+ /* ang1 should not be 0, but be paranoid */
+ *r_sinratio = (ang1 == 0.0f) ? 1.0f : sinf(ang2) / sinf(ang1);
+ retval = true;
}
else if (ok1 && !ok2) {
copy_v3_v3(meetco, meet1);
@@ -1041,13 +978,7 @@ static void offset_on_edge_between(
slide_dist(emid, v, e1->offset_r, meetco);
}
- /* offsets may have changed now */
- d = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e1->e, v)->co);
- if (fabsf(d - e1->offset_r) > BEVEL_EPSILON)
- e1->offset_r = d;
- d = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co);
- if (fabsf(d - e2->offset_l) > BEVEL_EPSILON)
- e2->offset_l = d;
+ return retval;
}
/* Offset by e->offset in plane with normal plane_no, on left if left==true,
@@ -1806,6 +1737,7 @@ static void build_boundary_terminal_edge(BevelParams *bp, BevVert *bv, EdgeHalf
}
}
+#if 0
/* Return a value that is v if v is within BEVEL_MAX_ADJUST_PCT of the spec (assumed positive),
* else clamp to make it at most that far away from spec */
static float clamp_adjust(float v, float spec)
@@ -1819,6 +1751,7 @@ static float clamp_adjust(float v, float spec)
else
return v;
}
+#endif
/* Make a circular list of BoundVerts for bv, each of which has the coordinates
* of a vertex on the boundary of the beveled vertex bv->v.
@@ -1835,11 +1768,10 @@ static float clamp_adjust(float v, float spec)
static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
{
MemArena *mem_arena = bp->mem_arena;
- EdgeHalf *efirst, *e, *e2, *e3, *enip, *eip, *eother;
+ EdgeHalf *efirst, *e, *e2, *e3, *enip, *eip, *eon;
BoundVert *v;
- BevVert *bvother;
VMesh *vm;
- float co[3];
+ float co[3], r;
int nip, nnip;
/* Current bevel does nothing if only one edge into a vertex */
@@ -1853,30 +1785,9 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
vm = bv->vmesh;
- /* Find a beveled edge to be efirst. Then for each edge, try matching widths to other end. */
+ /* Find a beveled edge to be efirst */
e = efirst = next_bev(bv, NULL);
BLI_assert(e->is_bev);
- do {
- eother = find_other_end_edge_half(bp, e, &bvother);
- if (eother && bvother->visited && bp->offset_type != BEVEL_AMT_PERCENT) {
- /* try to keep bevel even by matching other end offsets */
- /* sometimes, adjustment can accumulate errors so use the bp->limit_offset to
- * let user limit the adjustment to within a reasonable range around spec */
- if (bp->limit_offset) {
- e->offset_l = clamp_adjust(eother->offset_r, e->offset_l_spec);
- e->offset_r = clamp_adjust(eother->offset_l, e->offset_r_spec);
- }
- else {
- e->offset_l = eother->offset_r;
- e->offset_r = eother->offset_l;
- }
- }
- else {
- /* reset to user spec */
- e->offset_l = e->offset_l_spec;
- e->offset_r = e->offset_r_spec;
- }
- } while ((e = e->next) != efirst);
if (bv->selcount == 1) {
/* special case: only one beveled edge in */
@@ -1890,6 +1801,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
e = efirst;
do {
BLI_assert(e->is_bev);
+ eon = NULL;
/* Make the BoundVert for the right side of e; other side will be made
* when the beveled edge to the left of e is handled.
* Analyze edges until next beveled edge.
@@ -1913,7 +1825,8 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
else if (nnip > 0) {
if (bp->loop_slide && nnip == 1 && good_offset_on_edge_between(e, e2, enip, bv->v)) {
- offset_on_edge_between(bp, e, e2, enip, bv->v, co);
+ if (offset_on_edge_between(e, e2, enip, bv->v, co, &r))
+ eon = enip;
}
else {
offset_meet(e, e2, bv->v, NULL, true, co);
@@ -1922,7 +1835,8 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
else {
/* nip > 0 and nnip == 0 */
if (bp->loop_slide && nip == 1 && good_offset_on_edge_between(e, e2, eip, bv->v)) {
- offset_on_edge_between(bp, e, e2, eip, bv->v, co);
+ if (offset_on_edge_between(e, e2, eip, bv->v, co, &r))
+ eon = eip;
}
else {
offset_meet(e, e2, bv->v, e->fnext, true, co);
@@ -1933,6 +1847,9 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
v->efirst = e;
v->elast = e2;
v->ebev = e2;
+ v->eon = eon;
+ if (eon)
+ v->sinratio = r;
e->rightv = v;
e2->leftv = v;
for (e3 = e->next; e3 != e2; e3 = e3->next) {
@@ -1962,98 +1879,393 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
}
-/* Do a global pass to try to make offsets as even as possible.
- * Consider this graph:
- * nodes = BevVerts
- * edges = { (u,v) } where u and v are nodes such that u and v
- * are connected by a mesh edge that has at least one end
- * whose offset does not match the user spec.
- *
- * Do a breadth-first search on this graph, starting from nodes
- * that have any_adjust=true, and changing all
- * not-already-changed offsets on EdgeHalfs to match the
- * corresponding ones that changed on the other end.
- * The graph is dynamic in the sense that having an offset that
- * doesn't meet the user spec can be added as the search proceeds.
- * We want this search to be deterministic (not dependent
- * on order of processing through hash table), so as to avoid
- * flicker to to different decisions made if search is different
- * while dragging the offset number in the UI. So look for the
- * lower vertex number when there is a choice of where to start.
- *
- * Note that this might not process all BevVerts, only the ones
- * that need adjustment.
- */
-static void adjust_offsets(BevelParams *bp)
+#ifdef DEBUG_ADJUST
+static void print_adjust_stats(BoundVert *vstart)
{
- BevVert *bv, *searchbv, *bvother;
- int i, searchi;
- GHashIterator giter;
- EdgeHalf *e, *efirst, *eother;
- GSQueue *q;
- float max_rel_adj;
+ BoundVert *v;
+ EdgeHalf *eleft, *eright;
+ double even_residual2, spec_residual2;
+ double max_even_r, max_even_r_pct;
+ double max_spec_r, max_spec_r_pct;
+ double delta, delta_pct;
+
+ printf("\nSolution analysis\n");
+ even_residual2 = 0.0;
+ spec_residual2 = 0.0;
+ max_even_r = 0.0;
+ max_even_r_pct = 0.0;
+ max_spec_r = 0.0;
+ max_spec_r_pct = 0.0;
+ printf("width matching\n");
+ v = vstart;
+ do {
+ if (v->adjchain != NULL) {
+ eright = v->efirst;
+ eleft = v->adjchain->elast;
+ delta = fabs(eright->offset_r - eleft->offset_l);
+ delta_pct = 100.0 * delta / eright->offset_r_spec;
+ printf("e%d r(%f) vs l(%f): abs(delta)=%f, delta_pct=%f\n",
+ BM_elem_index_get(eright->e), eright->offset_r, eleft->offset_l, delta, delta_pct);
+ even_residual2 += delta * delta;
+ if (delta > max_even_r)
+ max_even_r = delta;
+ if (delta_pct > max_even_r_pct)
+ max_even_r_pct = delta_pct;
+ }
+ v = v->adjchain;
+ } while (v && v != vstart);
+
+ printf("spec matching\n");
+ v = vstart;
+ do {
+ if (v->adjchain != NULL) {
+ eright = v->efirst;
+ eleft = v->adjchain->elast;
+ delta = eright->offset_r - eright->offset_r_spec;
+ delta_pct = 100.0 * delta / eright->offset_r_spec;
+ printf("e%d r(%f) vs r spec(%f): delta=%f, delta_pct=%f\n",
+ BM_elem_index_get(eright->e), eright->offset_r, eright->offset_r_spec, delta, delta_pct);
+ spec_residual2 += delta * delta;
+ delta = fabs(delta);
+ delta_pct = fabs(delta_pct);
+ if (delta > max_spec_r)
+ max_spec_r = delta;
+ if (delta_pct > max_spec_r_pct)
+ max_spec_r_pct = delta_pct;
+
+ delta = eleft->offset_l - eleft->offset_l_spec;
+ delta_pct = 100.0 * delta / eright->offset_l_spec;
+ printf("e%d l(%f) vs l spec(%f): delta=%f, delta_pct=%f\n",
+ BM_elem_index_get(eright->e), eleft->offset_l, eleft->offset_l_spec, delta, delta_pct);
+ spec_residual2 += delta * delta;
+ delta = fabs(delta);
+ delta_pct = fabs(delta_pct);
+ if (delta > max_spec_r)
+ max_spec_r = delta;
+ if (delta_pct > max_spec_r_pct)
+ max_spec_r_pct = delta_pct;
+ }
+ v = v->adjchain;
+ } while (v && v != vstart);
+
+ printf("Analysis Result:\n");
+ printf("even residual2 = %f, spec residual2 = %f\n", even_residual2, spec_residual2);
+ printf("max even delta = %f, max as percent of spec = %f\n", max_even_r, max_even_r_pct);
+ printf("max spec delta = %f, max as percent of spec = %f\n", max_spec_r, max_spec_r_pct);
+}
+#endif
- BLI_assert(!bp->vertex_only);
- GHASH_ITER(giter, bp->vert_hash) {
- bv = BLI_ghashIterator_getValue(&giter);
- bv->visited = false;
+#ifdef FAST_ADJUST_CODE
+/* This code uses a direct solution to the adjustment problem for chains and certain cycles.
+ * It is a two-step approach: first solve for the exact solution of the 'match widths' constraints
+ * using the one degree of freedom that allows for expressing all other widths in terms of that.
+ * And then minimize the spec-matching constraints using the derivative of the least squares
+ * residual in terms of that one degree of freedom.
+ * Unfortunately, the results are in some cases worse than the general least squares solution
+ * for the combined (with weights) problem, so this code is not used.
+ * But keep it here for a while in case peformance issues demand that it be used sometimes. */
+static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscycle)
+{
+ BoundVert *v;
+ EdgeHalf *eleft, *eright;
+ float *g;
+ float *g_prod;
+ float gprod, gprod_sum, spec_sum, p;
+ int i;
+
+ g = MEM_mallocN(np * sizeof(float), "beveladjust");
+ g_prod = MEM_mallocN(np * sizeof(float), "beveladjust");
+
+ v = vstart;
+ spec_sum = 0.0f;
+ i = 0;
+ do {
+ g[i] = v->sinratio;
+ if (iscycle || v->adjchain != NULL) {
+ spec_sum += v->efirst->offset_r;
+ }
+ else {
+ spec_sum += v->elast->offset_l;
+ }
+ i++;
+ v = v->adjchain;
+ } while (v && v != vstart);
+
+ gprod = 1.00f;
+ gprod_sum = 1.0f;
+ for (i = np - 1; i > 0; i--) {
+ gprod *= g[i];
+ g_prod[i] = gprod;
+ gprod_sum += gprod;
+ }
+ g_prod[0] = 1.0f;
+ if (iscycle) {
+ gprod *= g[0];
+ if (fabs(gprod - 1.0f) > BEVEL_EPSILON) {
+ /* fast cycle calc only works if total product is 1 */
+ MEM_freeN(g);
+ MEM_freeN(g_prod);
+ return false;
+ }
}
+ if (gprod_sum == 0.0f) {
+ MEM_freeN(g);
+ MEM_freeN(g_prod);
+ return false;
+ }
+ p = spec_sum / gprod_sum;
- q = BLI_gsqueue_new(sizeof(BevVert *));
- /* the following loop terminates because at least one node is visited each time */
- for (;;) {
- /* look for root of a connected component in search graph */
- searchbv = NULL;
- searchi = -1;
- GHASH_ITER(giter, bp->vert_hash) {
- bv = BLI_ghashIterator_getValue(&giter);
- if (!bv->visited && max_edge_half_offset_rel_change(bv) > 0.0f) {
- i = BM_elem_index_get(bv->v);
- if (!searchbv || i < searchi) {
- searchbv = bv;
- searchi = i;
- }
+ /* apply the new offsets */
+ v = vstart;
+ i = 0;
+ do {
+ if (iscycle || v->adjchain != NULL) {
+ eright = v->efirst;
+ eleft = v->elast;
+ eright->offset_r = g_prod[(i + 1) % np] * p;
+ if (iscycle || v != vstart) {
+ eleft->offset_l = v->sinratio * eright->offset_r;
}
}
- if (searchbv == NULL)
- break;
+ else {
+ /* not a cycle, and last of chain */
+ eleft = v->elast;
+ eleft->offset_l = p;
+ }
+ i++;
+ v = v->adjchain;
+ } while (v && v != vstart);
- BLI_gsqueue_push(q, &searchbv);
- while (!BLI_gsqueue_is_empty(q)) {
- BLI_gsqueue_pop(q, &bv);
- /* If do this check, don't have to check for already-on-queue before push, below */
- if (bv->visited)
- continue;
- bv->visited = true;
- build_boundary(bp, bv, false);
-
- e = efirst = &bv->edges[0];
- do {
- eother = find_other_end_edge_half(bp, e, &bvother);
- if (eother && !bvother->visited && edge_half_offset_changed(e)) {
- BLI_gsqueue_push(q, &bvother);
+ MEM_freeN(g);
+ MEM_freeN(g_prod);
+ return true;
+}
+#endif
+
+/* Adjust the offsets for a single cycle or chain.
+ * For chains and some cycles, a fast solution exists.
+ * Otherwise, we set up and solve a linear least squares problem
+ * that tries to minimize the squared differences of lengths
+ * at each end of an edge, and (with smaller weight) the
+ * squared differences of the offsets from their specs.
+ */
+static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
+{
+ BoundVert *v;
+ EdgeHalf *eleft, *eright, *enextleft;
+ LinearSolver *solver;
+ double weight, val;
+ int i, np, nrows, row;
+
+ np = 0;
+#ifdef DEBUG_ADJUST
+ printf("\nadjust the %s (with eigen)\n", iscycle ? "cycle" : "chain");
+#endif
+ v = vstart;
+ do {
+#ifdef DEBUG_ADJUST
+ eleft = v->elast;
+ eright = v->efirst;
+ printf(" (left=e%d, right=e%d)", BM_elem_index_get(eleft->e), BM_elem_index_get(eright->e));
+#endif
+ np++;
+ v = v->adjchain;
+ } while (v && v != vstart);
+#ifdef DEBUG_ADJUST
+ printf(" -> %d parms\n", np);
+#endif
+
+#ifdef FAST_ADJUST_CODE
+ if (adjust_the_cycle_or_chain_fast(vstart, np, iscycle))
+ return;
+#endif
+
+ nrows = iscycle ? 3 * np : 3 * np - 3;
+
+ solver = EIG_linear_least_squares_solver_new(nrows, np, 1);
+
+ v = vstart;
+ i = 0;
+ weight = BEVEL_MATCH_SPEC_WEIGHT; /* sqrt of factor to weight down importance of spec match */
+ do {
+ /* except at end of chain, v's indep variable is offset_r of v->efirst */
+ if (iscycle || i < np - 1) {
+ eright = v->efirst;
+ eleft = v->elast;
+ enextleft = v->adjchain->elast;
+#ifdef DEBUG_ADJUST
+ printf("p%d: e%d->offset_r = %f\n", i, BM_elem_index_get(eright->e), eright->offset_r);
+ if (iscycle || v != vstart)
+ printf(" dependent: e%d->offset_l = %f * p%d\n", BM_elem_index_get(eleft->e), v->sinratio, i);
+#endif
+
+ /* residue i: width difference between eright and eleft of next */
+ EIG_linear_solver_matrix_add(solver, i, i, 1.0);
+ EIG_linear_solver_right_hand_side_add(solver, 0, i, 0.0);
+ if (iscycle) {
+ EIG_linear_solver_matrix_add(solver, i > 0 ? i - 1 : np - 1, i, -v->sinratio);
+ }
+ else {
+ if (i > 0) {
+ EIG_linear_solver_matrix_add(solver, i - 1, i, -v->sinratio);
}
- } while ((e = e->next) != efirst);
+ }
+
+ /* residue np + 2*i (if cycle) else np - 1 + 2*i:
+ * right offset for parm i matches its spec; weighted */
+ row = iscycle ? np + 2 * i : np - 1 + 2 * i;
+ EIG_linear_solver_matrix_add(solver, row, i, weight);
+ EIG_linear_solver_right_hand_side_add(solver, 0, row, weight * eright->offset_r);
+#ifdef DEBUG_ADJUST
+ printf("b[%d]=%f * %f, for e%d->offset_r\n", row, weight, eright->offset_r, BM_elem_index_get(eright->e));
+#endif
+
+ /* residue np + 2*i + 1 (if cycle) else np - 1 + 2*i + 1:
+ * left offset for parm i matches its spec; weighted */
+ row = row + 1;
+ EIG_linear_solver_matrix_add(solver, row, (i == np - 1) ? 0 : i + 1, weight * v->adjchain->sinratio);
+ EIG_linear_solver_right_hand_side_add(solver, 0, row, weight * enextleft->offset_l);
+#ifdef DEBUG_ADJUST
+ printf("b[%d]=%f * %f, for e%d->offset_l\n", row, weight, enextleft->offset_l,
+ BM_elem_index_get(enextleft->e));
+#endif
}
- }
- BLI_gsqueue_free(q);
+ else {
+ /* not a cycle, and last of chain */
+ eleft = v->elast;
+#ifdef DEBUG_ADJUST
+ printf("p%d: e%d->offset_l = %f\n", i, BM_elem_index_get(eleft->e), eleft->offset_l);
+#endif
+ /* second part of residue i for last i */
+ EIG_linear_solver_matrix_add(solver, i - 1, i, -1.0);
+ }
+ i++;
+ v = v->adjchain;
+ } while (v && v != vstart);
+ EIG_linear_solver_solve(solver);
+#ifdef DEBUG_ADJUST
+ /* Note: this print only works after solve, but by that time b has been cleared */
+ EIG_linear_solver_print_matrix(solver);
+ printf("\nSolution:\n");
+ for (i = 0; i < np; i++)
+ printf("p%d = %f\n", i, EIG_linear_solver_variable_get(solver, 0, i));
+#endif
- /* Should we auto-limit the error accumulation? Typically, spirals can lead to 100x relative adjustments,
- * and somewhat hacky mechanism of using bp->limit_offset to indicate "clamp the adjustments" is not
- * obvious to users, who almost certainly want clamping in this situation.
- * The reason not to clamp always is that some models work better without it (e.g., Bent_test in regression
- * suite, where relative adjust maximum is about .6). */
- if (!bp->limit_offset) {
- max_rel_adj = 0.0f;
- GHASH_ITER(giter, bp->vert_hash) {
- bv = BLI_ghashIterator_getValue(&giter);
- max_rel_adj = max_ff(max_rel_adj, max_edge_half_offset_rel_change(bv));
+ /* Use the solution to set new widths */
+ v = vstart;
+ i = 0;
+ do {
+ val = EIG_linear_solver_variable_get(solver, 0, i);
+ if (iscycle || i < np - 1) {
+ eright = v->efirst;
+ eleft = v->elast;
+ eright->offset_r = (float)val;
+#ifdef DEBUG_ADJUST
+ printf("e%d->offset_r = %f\n", BM_elem_index_get(eright->e), eright->offset_r);
+#endif
+ if (iscycle || v != vstart) {
+ eleft->offset_l = (float)(v->sinratio * val);
+#ifdef DEBUG_ADJUST
+ printf("e%d->offset_l = %f\n", BM_elem_index_get(eleft->e), eleft->offset_l);
+#endif
+ }
}
- if (max_rel_adj > BEVEL_MAX_AUTO_ADJUST_PCT / 100.0f) {
- bp->limit_offset = true;
- adjust_offsets(bp);
- bp->limit_offset = false;
+ else {
+ /* not a cycle, and last of chain */
+ eleft = v->elast;
+ eleft->offset_l = (float)val;
+#ifdef DEBUG_ADJUST
+ printf("e%d->offset_l = %f\n", BM_elem_index_get(eleft->e), eleft->offset_l);
+#endif
}
+ i++;
+ v = v->adjchain;
+ } while (v && v != vstart);
+
+#ifdef DEBUG_ADJUST
+ print_adjust_stats(vstart);
+ EIG_linear_solver_print_matrix(solver);
+#endif
+
+ EIG_linear_solver_delete(solver);
+}
+
+/* Adjust the offsets to try to make them, as much as possible,
+ * have even-width bevels with offsets that match their specs.
+ * The problem that we can try to amelieroate is that when loop slide
+ * is active, the meet point will probably not be the one that makes
+ * both sides have their specified width. And because both ends may be
+ * on loop slide edges, the widths at each end could be different.
+ *
+ * It turns out that the dependent offsets either form chains or
+ * cycles, and we can process each of those separatey.
+ */
+static void adjust_offsets(BevelParams *bp)
+{
+ BevVert *bv, *bvcur;
+ BoundVert *v, *vanchor, *vchainstart, *vnext;
+ EdgeHalf *enext;
+ GHashIterator giter;
+ bool iscycle;
+
+ /* find and process chains and cycles of unvisited BoundVerts that have eon set */
+ GHASH_ITER(giter, bp->vert_hash) {
+ bv = bvcur = BLI_ghashIterator_getValue(&giter);
+ vanchor = bv->vmesh->boundstart;
+ do {
+ if (vanchor->visited || !vanchor->eon)
+ continue;
+
+ /* Find one of (1) a cycle that starts and ends at v
+ * where each v has v->eon set and had not been visited before;
+ * or (2) a chain of v's where the start and end of the chain do not have
+ * v->eon set but all else do.
+ * It is OK for the first and last elements to
+ * have been visited before, but not any of the inner ones.
+ * We chain the v's together through v->adjchain, and are following
+ * them in left->right direction, meaning that the left side of one edge
+ * pairs with the right side of the next edge in the cycle or chain. */
+
+ /* first follow paired edges in left->right direction */
+ v = vchainstart = vanchor;
+ iscycle = false;
+ while (v->eon && !v->visited && !iscycle) {
+ enext = find_other_end_edge_half(bp, v->efirst, &bvcur);
+ BLI_assert(enext != NULL);
+ vnext = enext->leftv;
+ v->adjchain = vnext;
+ v->visited = true;
+ if (vnext->visited) {
+ if (vnext != vchainstart) {
+ break;
+ }
+ adjust_the_cycle_or_chain(vchainstart, true);
+ iscycle = true;
+ }
+ v = vnext;
+ }
+ if (!iscycle) {
+ /* right->left direction, changing vchainstart at each step */
+ v = vchainstart;
+ bvcur = bv;
+ do {
+ enext = find_other_end_edge_half(bp, v->elast, &bvcur);
+ BLI_assert(enext != NULL);
+ vnext = enext->rightv;
+ vnext->adjchain = v;
+ vchainstart = vnext;
+ v->visited = true;
+ v = vnext;
+ } while (!v->visited && v->eon);
+ adjust_the_cycle_or_chain(vchainstart, false);
+ }
+ } while ((vanchor = vanchor->next) != bv->vmesh->boundstart);
+ }
+
+ /* Rebuild boundaries with new width specs */
+ GHASH_ITER(giter, bp->vert_hash) {
+ bv = BLI_ghashIterator_getValue(&giter);
+ build_boundary(bp, bv, false);
}
}
@@ -2997,7 +3209,7 @@ static void build_center_ngon(BMesh *bm, BevVert *bv, int mat_nr)
BLI_array_append(ve, NULL);
}
} while ((v = v->next) != vm->boundstart);
- bev_create_ngon(bm, vv, BLI_array_count(vv), vf, frep, ve, mat_nr, true);
+ bev_create_ngon(bm, vv, BLI_array_len(vv), vf, frep, ve, mat_nr, true);
BLI_array_free(vv);
BLI_array_free(vf);
@@ -3041,6 +3253,173 @@ static void build_square_in_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv, VMesh
}
}
+/* copy whichever of a and b is closer to v into r */
+static void closer_v3_v3v3v3(float r[3], float a[3], float b[3], float v[3])
+{
+ if (len_squared_v3v3(a, v) <= len_squared_v3v3(b, v))
+ copy_v3_v3(r, a);
+ else
+ copy_v3_v3(r, b);
+}
+
+/* Special case of VMesh when profile == 1 and there are 3 or more beveled edges.
+ * We want the effect of parallel offset lines (n/2 of them) on each side of the center, for even n.
+ * Wherever they intersect with each other between two successive beveled edges, those intersections
+ * are part of the vmesh rings.
+ * We have to move the boundary edges too -- the usual method is to make one profile plane between
+ * successive BoundVerts, but for the effect we want here, there will be two planes, one on each side
+ * of the original edge.
+ */
+static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
+{
+ int n, ns, ns2, odd, i, j, k, ikind, im1, clstride;
+ float bndco[3], dir1[3], dir2[3], co1[3], co2[3], meet1[3], meet2[3], v1co[3], v2co[3];
+ float *on_edge_cur, *on_edge_prev, *p;
+ float ns2inv, finalfrac, ang;
+ BoundVert *bndv;
+ EdgeHalf *e1, *e2;
+ VMesh *vm;
+ float *centerline;
+
+ n = bv->vmesh->count;
+ ns = bv->vmesh->seg;
+ ns2 = ns / 2;
+ odd = ns % 2;
+ ns2inv = 1.0f / (float) ns2;
+ vm = new_adj_vmesh(bp->mem_arena, n, ns, bv->vmesh->boundstart);
+ clstride = 3 * (ns2 + 1);
+ centerline = MEM_mallocN(clstride * n * sizeof(float), "bevel");
+
+ /* find on_edge, place on bndv[i]'s elast where offset line would meet,
+ * averaging with position where next sector's offset line would meet */
+ bndv = vm->boundstart;
+ for (i = 0; i < n; i++) {
+ copy_v3_v3(bndco, bndv->nv.co);
+ e1 = bndv->efirst;
+ e2 = bndv->elast;
+ sub_v3_v3v3(dir1, e1->e->v1->co, e1->e->v2->co);
+ sub_v3_v3v3(dir2, e2->e->v1->co, e2->e->v2->co);
+ add_v3_v3v3(co1, bndco, dir1);
+ add_v3_v3v3(co2, bndco, dir2);
+ /* intersect e1 with line through bndv parallel to e2 to get v1co */
+ ikind = isect_line_line_v3(e1->e->v1->co, e1->e->v2->co, bndco, co2, meet1, meet2);
+
+ if (ikind == 0) {
+ /* Placeholder: this should get eliminated by min dist test with adjacent edge */
+ mid_v3_v3v3(v1co, e1->e->v1->co, e1->e->v2->co);
+ }
+ else {
+ /* if the lines are skew (ikind == 2), want meet1 which is on e1 */
+ copy_v3_v3(v1co, meet1);
+ }
+ /* intersect e2 with line through bndv parallel to e1 to get v2co */
+ ikind = isect_line_line_v3(e2->e->v1->co, e2->e->v2->co, bndco, co1, meet1, meet2);
+ if (ikind == 0) {
+ mid_v3_v3v3(v2co, e2->e->v1->co, e2->e->v2->co);
+ }
+ else {
+ copy_v3_v3(v2co, meet1);
+ }
+
+ /* want on_edge[i] to be min dist to bv->v of v2co and the v1co of next iteration */
+ on_edge_cur = centerline + clstride * i;
+ on_edge_prev = centerline + clstride * ((i == 0) ? n - 1 : i - 1);
+ if (i == 0) {
+ copy_v3_v3(on_edge_cur, v2co);
+ copy_v3_v3(on_edge_prev, v1co);
+ }
+ else if (i == n - 1) {
+ closer_v3_v3v3v3(on_edge_cur, on_edge_cur, v2co, bv->v->co);
+ closer_v3_v3v3v3(on_edge_prev, on_edge_prev, v1co, bv->v->co);
+ }
+ else {
+ copy_v3_v3(on_edge_cur, v2co);
+ closer_v3_v3v3v3(on_edge_prev, on_edge_prev, v1co, bv->v->co);
+ }
+ bndv = bndv->next;
+ }
+
+ /* fill in rest of centerlines by interpolation */
+ copy_v3_v3(co2, bv->v->co);
+ bndv = vm->boundstart;
+ for (i = 0; i < n; i++) {
+ if (odd) {
+ ang = 0.5f * angle_v3v3v3(bndv->nv.co, co1, bndv->next->nv.co);
+ if (ang > BEVEL_SMALL_ANG) {
+ /* finalfrac is length along arms of isoceles triangle with top angle 2*ang
+ * such that the base of the triangle is 1.
+ * This is used in interpolation along centerline in odd case.
+ * To avoid too big a drop from bv, cap finalfrac a 0.8 arbitrarily */
+ finalfrac = 0.5f / sin(ang);
+ if (finalfrac > 0.8f)
+ finalfrac = 0.8f;
+ }
+ else {
+ finalfrac = 0.8f;
+ }
+ ns2inv = 1.0f / (ns2 + finalfrac);
+ }
+
+ p = centerline + clstride * i;
+ copy_v3_v3(co1, p);
+ p += 3;
+ for (j = 1; j <= ns2; j++) {
+ interp_v3_v3v3(p, co1, co2, j * ns2inv);
+ p += 3;
+ }
+ bndv = bndv->next;
+ }
+
+ /* coords of edges and mid or near-mid line */
+ bndv = vm->boundstart;
+ for (i = 0; i < n; i++) {
+ copy_v3_v3(co1, bndv->nv.co);
+ copy_v3_v3(co2, centerline + clstride * (i == 0 ? n - 1 : i - 1));
+ for (j = 0; j < ns2 + odd; j++) {
+ interp_v3_v3v3(mesh_vert(vm, i, j, 0)->co, co1, co2, j * ns2inv);
+ }
+ copy_v3_v3(co2, centerline + clstride * i);
+ for (k = 1; k <= ns2; k++) {
+ interp_v3_v3v3(mesh_vert(vm, i, 0, k)->co, co1, co2, k * ns2inv);
+ }
+ bndv = bndv->next;
+ }
+ if (!odd)
+ copy_v3_v3(mesh_vert(vm, 0, ns2, ns2)->co, bv->v->co);
+ vmesh_copy_equiv_verts(vm);
+
+ /* fill in interior points by interpolation from edges to centerlines */
+ bndv = vm->boundstart;
+ for (i = 0; i < n; i++) {
+ im1 = (i == 0) ? n - 1 : i - 1;
+ for (j = 1; j < ns2 + odd; j++) {
+ for (k = 1; k <= ns2; k++) {
+ ikind = isect_line_line_v3(
+ mesh_vert(vm, i, 0, k)->co, centerline + clstride * im1 + 3 * k,
+ mesh_vert(vm, i, j, 0)->co, centerline + clstride * i + 3 * j,
+ meet1, meet2);
+ if (ikind == 0) {
+ /* how can this happen? fall back on interpolation in one direction if it does */
+ interp_v3_v3v3(mesh_vert(vm, i, j, k)->co,
+ mesh_vert(vm, i, 0, k)->co, centerline + clstride * im1 + 3 * k, j * ns2inv);
+ }
+ else if (ikind == 1) {
+ copy_v3_v3(mesh_vert(vm, i, j, k)->co, meet1);
+ }
+ else {
+ mid_v3_v3v3(mesh_vert(vm, i, j, k)->co, meet1, meet2);
+ }
+ }
+ }
+ bndv = bndv->next;
+ }
+
+ vmesh_copy_equiv_verts(vm);
+
+ MEM_freeN(centerline);
+ return vm;
+}
+
/*
* Given that the boundary is built and the boundary BMVerts have been made,
* calculate the positions of the interior mesh points for the M_ADJ pattern,
@@ -3063,9 +3442,13 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
odd = ns % 2;
BLI_assert(n >= 3 && ns > 1);
+
vpipe = pipe_test(bv);
- if (vpipe) {
+ if (bp->pro_super_r == PRO_SQUARE_R && bv->selcount >= 3 && !odd) {
+ vm1 = square_out_adj_vmesh(bp, bv);
+ }
+ else if (vpipe) {
vm1 = pipe_adj_vmesh(bp, bv, vpipe);
}
else if (tri_corner_test(bp, bv)) {
@@ -3577,7 +3960,7 @@ static int bevel_edge_order_extend(BMesh *bm, BevVert *bv, int i)
BLI_array_append(sucs, bme2);
}
}
- nsucs = BLI_array_count(sucs);
+ nsucs = BLI_array_len(sucs);
bestj = j = i;
for (sucindex = 0; sucindex < nsucs; sucindex++) {
@@ -3590,7 +3973,7 @@ static int bevel_edge_order_extend(BMesh *bm, BevVert *bv, int i)
tryj = bevel_edge_order_extend(bm, bv, j + 1);
if (tryj > bestj || (tryj == bestj && edges_face_connected_at_vert(bv->edges[tryj].e, bv->edges[0].e))) {
bestj = tryj;
- BLI_array_empty(save_path);
+ BLI_array_clear(save_path);
for (k = j + 1; k <= bestj; k++) {
BLI_array_append(save_path, bv->edges[k].e);
}
@@ -4117,15 +4500,15 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
}
}
if (do_rebuild) {
- n = BLI_array_count(vv);
+ n = BLI_array_len(vv);
f_new = bev_create_ngon(bm, vv, n, NULL, f, NULL, -1, true);
- for (k = 0; k < BLI_array_count(vv_fix); k++) {
+ for (k = 0; k < BLI_array_len(vv_fix); k++) {
bev_merge_uvs(bm, vv_fix[k]);
}
/* copy attributes from old edges */
- BLI_assert(n == BLI_array_count(ee));
+ BLI_assert(n == BLI_array_len(ee));
bme_prev = ee[n - 1];
for (k = 0; k < n; k++) {
bme_new = BM_edge_exists(vv[k], vv[(k + 1) % n]);
@@ -4983,6 +5366,7 @@ void BM_mesh_bevel(
bp.use_weights = use_weights;
bp.loop_slide = loop_slide;
bp.limit_offset = limit_offset;
+ bp.offset_adjust = true;
bp.dvert = dvert;
bp.vertex_group = vertex_group;
bp.mat_nr = mat;
@@ -5019,7 +5403,7 @@ void BM_mesh_bevel(
}
/* Perhaps do a pass to try to even out widths */
- if (!bp.vertex_only) {
+ if (!bp.vertex_only && bp.offset_adjust) {
adjust_offsets(&bp);
}
diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
index 0a1271c2aa9..c1b2bc2625b 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
@@ -38,8 +38,8 @@
#include "BLI_alloca.h"
#include "BLI_memarena.h"
#include "BLI_edgehash.h"
-#include "BLI_polyfill2d.h"
-#include "BLI_polyfill2d_beautify.h"
+#include "BLI_polyfill_2d.h"
+#include "BLI_polyfill_2d_beautify.h"
#include "BLI_utildefines_stack.h"
@@ -1357,7 +1357,7 @@ void BM_mesh_decimate_collapse(
(BLI_heap_node_value(BLI_heap_top(eheap)) != COST_INVALID))
{
// const float value = BLI_heap_node_value(BLI_heap_top(eheap));
- BMEdge *e = BLI_heap_popmin(eheap);
+ BMEdge *e = BLI_heap_pop_min(eheap);
float optimize_co[3];
BLI_assert(BM_elem_index_get(e) < tot_edge_orig); /* handy to detect corruptions elsewhere */
@@ -1388,7 +1388,7 @@ void BM_mesh_decimate_collapse(
* - edges sharing a vertex are ignored, so the pivot vertex isnt moved to one side.
*/
- BMEdge *e = BLI_heap_popmin(eheap);
+ BMEdge *e = BLI_heap_pop_min(eheap);
const int e_index = BM_elem_index_get(e);
const int e_index_mirr = edge_symmetry_map[e_index];
BMEdge *e_mirr = NULL;
diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c
index 193a032b46e..df9d07036af 100644
--- a/source/blender/bmesh/tools/bmesh_edgenet.c
+++ b/source/blender/bmesh/tools/bmesh_edgenet.c
@@ -335,7 +335,7 @@ static LinkNode *bm_edgenet_path_calc(
BLI_linklist_free_pool(v_ls_next, NULL, path_pool);
BLI_linklist_free_pool(v_ls_prev, NULL, path_pool);
- // BLI_assert(BLI_mempool_count(path_pool) == 0);
+ // BLI_assert(BLI_mempool_len(path_pool) == 0);
path_len = bm_edgenet_path_from_pass(e_found->v1, &path, vnet_info, path_pool);
BLI_linklist_reverse(&path);
@@ -505,7 +505,7 @@ void BM_mesh_edgenet(
}
BLI_linklist_free_pool(path, NULL, path_pool);
- BLI_assert(BLI_mempool_count(path_pool) == 0);
+ BLI_assert(BLI_mempool_len(path_pool) == 0);
}
bm->elem_index_dirty |= BM_FACE | BM_LOOP;
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c
index 82545a5e011..cc8511c65f1 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.c
+++ b/source/blender/bmesh/tools/bmesh_intersect.c
@@ -1265,8 +1265,8 @@ bool BM_mesh_intersect(
}
}
- splice_ls = MEM_mallocN(BLI_gset_size(s.wire_edges) * sizeof(*splice_ls), __func__);
- STACK_INIT(splice_ls, BLI_gset_size(s.wire_edges));
+ splice_ls = MEM_mallocN(BLI_gset_len(s.wire_edges) * sizeof(*splice_ls), __func__);
+ STACK_INIT(splice_ls, BLI_gset_len(s.wire_edges));
for (node = s.vert_dissolve; node; node = node->next) {
BMEdge *e_pair[2];
@@ -1669,7 +1669,7 @@ bool BM_mesh_intersect(
}
}
- has_edit_isect = (BLI_ghash_size(s.face_edges) != 0);
+ has_edit_isect = (BLI_ghash_len(s.face_edges) != 0);
/* cleanup */
BLI_ghash_free(s.edgetri_cache, NULL, NULL);
diff --git a/source/blender/bmesh/tools/bmesh_path.c b/source/blender/bmesh/tools/bmesh_path.c
index 85c591b6684..cc5ac6dd8ce 100644
--- a/source/blender/bmesh/tools/bmesh_path.c
+++ b/source/blender/bmesh/tools/bmesh_path.c
@@ -174,7 +174,7 @@ LinkNode *BM_mesh_calc_path_vert(
cost[BM_elem_index_get(v_src)] = 0.0f;
while (!BLI_heap_is_empty(heap)) {
- v = BLI_heap_popmin(heap);
+ v = BLI_heap_pop_min(heap);
if (v == v_dst)
break;
@@ -346,7 +346,7 @@ LinkNode *BM_mesh_calc_path_edge(
cost[BM_elem_index_get(e_src)] = 0.0f;
while (!BLI_heap_is_empty(heap)) {
- e = BLI_heap_popmin(heap);
+ e = BLI_heap_pop_min(heap);
if (e == e_dst)
break;
@@ -532,7 +532,7 @@ LinkNode *BM_mesh_calc_path_face(
cost[BM_elem_index_get(f_src)] = 0.0f;
while (!BLI_heap_is_empty(heap)) {
- f = BLI_heap_popmin(heap);
+ f = BLI_heap_pop_min(heap);
if (f == f_dst)
break;
diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c
index 2abf8f2c46e..e83ba73ad01 100644
--- a/source/blender/bmesh/tools/bmesh_region_match.c
+++ b/source/blender/bmesh/tools/bmesh_region_match.c
@@ -421,8 +421,8 @@ static void bm_uuidwalk_rehash(
UUID_Int *uuid_store;
uint i;
- uint rehash_store_len_new = MAX2(BLI_ghash_size(uuidwalk->verts_uuid),
- BLI_ghash_size(uuidwalk->faces_uuid));
+ uint rehash_store_len_new = MAX2(BLI_ghash_len(uuidwalk->verts_uuid),
+ BLI_ghash_len(uuidwalk->faces_uuid));
bm_uuidwalk_rehash_reserve(uuidwalk, rehash_store_len_new);
uuid_store = uuidwalk->cache.rehash_store;
@@ -520,8 +520,8 @@ static void bm_uuidwalk_pass_add(
verts_uuid_pass = uuidwalk->cache.verts_uuid;
faces_step_next = uuidwalk->cache.faces_step;
- BLI_assert(BLI_ghash_size(verts_uuid_pass) == 0);
- BLI_assert(BLI_gset_size(faces_step_next) == 0);
+ BLI_assert(BLI_ghash_len(verts_uuid_pass) == 0);
+ BLI_assert(BLI_gset_len(faces_step_next) == 0);
/* Add the face_step data from connected faces, creating new passes */
fstep = BLI_mempool_alloc(uuidwalk->step_pool);
@@ -659,7 +659,7 @@ static bool bm_uuidwalk_facestep_begin(
LinkNode *f_link, *f_link_next, **f_link_prev_p;
bool ok = false;
- BLI_assert(BLI_ghash_size(uuidwalk->cache.faces_from_uuid) == 0);
+ BLI_assert(BLI_ghash_len(uuidwalk->cache.faces_from_uuid) == 0);
BLI_assert(BLI_listbase_is_empty(&fstep->items));
f_link_prev_p = &fstep->faces;
@@ -864,7 +864,7 @@ static BMFace **bm_mesh_region_match_pair(
break;
}
- found = (BLI_ghash_size(w_dst->faces_uuid) == faces_src_region_len);
+ found = (BLI_ghash_len(w_dst->faces_uuid) == faces_src_region_len);
if (found) {
break;
}
@@ -877,7 +877,7 @@ static BMFace **bm_mesh_region_match_pair(
if (found) {
GHashIterator gh_iter;
- const uint faces_result_len = BLI_ghash_size(w_dst->faces_uuid);
+ const uint faces_result_len = BLI_ghash_len(w_dst->faces_uuid);
uint i;
faces_result = MEM_mallocN(sizeof(*faces_result) * (faces_result_len + 1), __func__);
diff --git a/source/blender/bmesh/tools/bmesh_separate.c b/source/blender/bmesh/tools/bmesh_separate.c
index 287b4125330..b3d0c339885 100644
--- a/source/blender/bmesh/tools/bmesh_separate.c
+++ b/source/blender/bmesh/tools/bmesh_separate.c
@@ -122,7 +122,7 @@ void BM_mesh_separate_faces(
/* Perform the split */
BM_face_loop_separate_multi(bm, loop_split.data, loop_split.count);
- BLI_buffer_empty(&loop_split);
+ BLI_buffer_clear(&loop_split);
}
} while ((l_iter = l_iter->next) != l_first);
}
diff --git a/source/blender/bmesh/tools/bmesh_triangulate.c b/source/blender/bmesh/tools/bmesh_triangulate.c
index bd201fa89bf..a3a3355d20f 100644
--- a/source/blender/bmesh/tools/bmesh_triangulate.c
+++ b/source/blender/bmesh/tools/bmesh_triangulate.c
@@ -38,8 +38,8 @@
#include "BLI_linklist.h"
/* only for defines */
-#include "BLI_polyfill2d.h"
-#include "BLI_polyfill2d_beautify.h"
+#include "BLI_polyfill_2d.h"
+#include "BLI_polyfill_2d_beautify.h"
#include "bmesh.h"
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp
index 6e59a404e47..2f692cb0f33 100644
--- a/source/blender/collada/AnimationExporter.cpp
+++ b/source/blender/collada/AnimationExporter.cpp
@@ -34,7 +34,7 @@ void forEachObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set)
}
}
-bool AnimationExporter::exportAnimations(const struct EvaluationContext *eval_ctx, Scene *sce)
+bool AnimationExporter::exportAnimations(Scene *sce)
{
bool has_animations = hasAnimations(sce);
if (has_animations) {
@@ -50,40 +50,265 @@ bool AnimationExporter::exportAnimations(const struct EvaluationContext *eval_ct
return has_animations;
}
-// called for each exported object
+bool AnimationExporter::is_flat_line(std::vector<float> &values, int channel_count)
+{
+ for (int i = 0; i < values.size(); i += channel_count) {
+ for (int j = 0; j < channel_count; j++) {
+ if (!bc_in_range(values[j], values[i+j], 0.000001))
+ return false;
+ }
+ }
+ return true;
+}
+/*
+ * This function creates a complete LINEAR Collada <Animation> Entry with all needed
+ * <source>, <sampler>, and <channel> entries.
+ * This is is used for creating sampled Transformation Animations for either:
+ *
+ * 1-axis animation:
+ * times contains the time points in seconds from within the timeline
+ * values contains the data (list of single floats)
+ * channel_count = 1
+ * axis_name = ['X' | 'Y' | 'Z']
+ * is_rot indicates if the animation is a rotation
+ *
+ * 3-axis animation:
+ * times contains the time points in seconds from within the timeline
+ * values contains the data (list of floats where each 3 entries are one vector)
+ * channel_count = 3
+ * axis_name = "" (actually not used)
+ * is_rot = false (see xxx below)
+ *
+ * xxx: I tried to create a 3 axis rotation animation
+ * like for translation or scale. But i could not
+ * figure out how to setup the channel for this case.
+ * So for now rotations are exported as 3 separate 1-axis collada animations
+ * See export_sampled_animation() further down.
+ */
+void AnimationExporter::create_sampled_animation(int channel_count,
+ std::vector<float> &times,
+ std::vector<float> &values,
+ std::string ob_name,
+ std::string label,
+ std::string axis_name,
+ bool is_rot)
+{
+ char anim_id[200];
+
+ if (is_flat_line(values, channel_count))
+ return;
+
+ BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(), label.c_str(), axis_name.c_str());
+
+ openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
+
+ /* create input source */
+ std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, times, false, anim_id, "");
+
+ /* create output source */
+ std::string output_id;
+ if (channel_count == 1)
+ output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, &values[0], values.size(), is_rot, anim_id, axis_name.c_str());
+ else if (channel_count == 3)
+ output_id = create_xyz_source(&values[0], times.size(), anim_id);
+ else if (channel_count == 16)
+ output_id = create_4x4_source(times, values, anim_id);
+
+ std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
+ COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
+ std::string empty;
+ sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
+ sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
+
+ /* TODO create in/out tangents source (LINEAR) */
+ std::string interpolation_id = fake_interpolation_source(times.size(), anim_id, "");
+
+ /* Create Sampler */
+ sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
+ addSampler(sampler);
+
+ /* Create channel */
+ std::string target = translate_id(ob_name) + "/" + label + axis_name + ((is_rot) ? ".ANGLE" : "");
+ addChannel(COLLADABU::URI(empty, sampler_id), target);
+
+ closeAnimation();
+
+}
+
+/*
+ * Export all animation FCurves of an Object.
+ *
+ * Note: This uses the keyframes as sample points,
+ * and exports "baked keyframes" while keeping the tangent infromation
+ * of the FCurves intact. This works for simple cases, but breaks
+ * especially when negative scales are involved in the animation.
+ *
+ * If it is necessary to conserve the Animation precisely then
+ * use export_sampled_animation_set() instead.
+ */
+void AnimationExporter::export_keyframed_animation_set(Object *ob)
+{
+ FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
+ if (!fcu) {
+ return; /* object has no animation */
+ }
+
+ if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) {
+
+ std::vector<float> ctimes;
+ find_keyframes(ob, ctimes);
+ if (ctimes.size() > 0)
+ export_sampled_matrix_animation(ob, ctimes);
+ }
+ else {
+ char *transformName;
+ while (fcu) {
+ //for armature animations as objects
+ if (ob->type == OB_ARMATURE)
+ transformName = fcu->rna_path;
+ else
+ transformName = extract_transform_name(fcu->rna_path);
+
+ if (
+ STREQ(transformName, "location") ||
+ STREQ(transformName, "scale") ||
+ (STREQ(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) ||
+ STREQ(transformName, "rotation_quaternion"))
+ {
+ create_keyframed_animation(ob, fcu, transformName, false);
+ }
+ fcu = fcu->next;
+ }
+ }
+}
+
+/*
+ * Export the sampled animation of an Object.
+ *
+ * Note: This steps over all animation frames (step size is given in export_settings.sample_size)
+ * and then evaluates the transformation,
+ * and exports "baked samples" This works always, however currently the interpolation type is set
+ * to LINEAR for now. (maybe later this can be changed to BEZIER)
+ *
+ * Note: If it is necessary to keep the FCurves intact, then use export_keyframed_animation_set() instead.
+ * However be aware that exporting keyframed animation may modify the animation slightly.
+ * Also keyframed animation exports tend to break when negative scales are involved.
+ */
+void AnimationExporter::export_sampled_animation_set(Object *ob)
+{
+ std::vector<float>ctimes;
+ find_sampleframes(ob, ctimes);
+ if (ctimes.size() > 0) {
+ if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX)
+ export_sampled_matrix_animation(ob, ctimes);
+ else
+ export_sampled_transrotloc_animation(ob, ctimes);
+ }
+}
+
+void AnimationExporter::export_sampled_matrix_animation(Object *ob, std::vector<float> &ctimes)
+{
+ UnitConverter converter;
+
+ std::vector<float> values;
+
+ for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime) {
+ float fmat[4][4];
+
+ bc_update_scene(eval_ctx, scene, *ctime);
+ BKE_object_matrix_local_get(ob, fmat);
+ if (this->export_settings->limit_precision)
+ bc_sanitize_mat(fmat, 6);
+
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ values.push_back(fmat[i][j]);
+ }
+
+ std::string ob_name = id_name(ob);
+
+ create_sampled_animation(16, ctimes, values, ob_name, "transform", "", false);
+}
+
+void AnimationExporter::export_sampled_transrotloc_animation(Object *ob, std::vector<float> &ctimes)
+{
+ static int LOC = 0;
+ static int EULX = 1;
+ static int EULY = 2;
+ static int EULZ = 3;
+ static int SCALE = 4;
+
+ std::vector<float> baked_curves[5];
+
+ for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime ) {
+ float fmat[4][4];
+ float floc[3];
+ float fquat[4];
+ float fsize[3];
+ float feul[3];
+
+ bc_update_scene(eval_ctx, scene, *ctime);
+ BKE_object_matrix_local_get(ob, fmat);
+ mat4_decompose(floc, fquat, fsize, fmat);
+ quat_to_eul(feul, fquat);
+
+ baked_curves[LOC].push_back(floc[0]);
+ baked_curves[LOC].push_back(floc[1]);
+ baked_curves[LOC].push_back(floc[2]);
+
+ baked_curves[EULX].push_back(feul[0]);
+ baked_curves[EULY].push_back(feul[1]);
+ baked_curves[EULZ].push_back(feul[2]);
+
+ baked_curves[SCALE].push_back(fsize[0]);
+ baked_curves[SCALE].push_back(fsize[1]);
+ baked_curves[SCALE].push_back(fsize[2]);
+
+ }
+
+ std::string ob_name = id_name(ob);
+
+ create_sampled_animation(3, ctimes, baked_curves[SCALE], ob_name, "scale", "", false);
+ create_sampled_animation(3, ctimes, baked_curves[LOC], ob_name, "location", "", false);
+
+ /* Not sure how to export rotation as a 3channel animation,
+ * so separate into 3 single animations for now:
+ */
+
+ create_sampled_animation(1, ctimes, baked_curves[EULX], ob_name, "rotation", "X", true);
+ create_sampled_animation(1, ctimes, baked_curves[EULY], ob_name, "rotation", "Y", true);
+ create_sampled_animation(1, ctimes, baked_curves[EULZ], ob_name, "rotation", "Z", true);
+
+ fprintf(stdout, "Animation Export: Baked %d frames for %s (sampling rate: %d)\n",
+ (int)baked_curves[0].size(),
+ ob->id.name,
+ this->export_settings->sampling_rate);
+}
+
+/* called for each exported object */
void AnimationExporter::operator()(Object *ob)
{
- FCurve *fcu;
char *transformName;
+
/* bool isMatAnim = false; */ /* UNUSED */
//Export transform animations
if (ob->adt && ob->adt->action) {
- fcu = (FCurve *)ob->adt->action->curves.first;
- //transform matrix export for bones are temporarily disabled here.
if (ob->type == OB_ARMATURE) {
+ /* Export skeletal animation (if any)*/
bArmature *arm = (bArmature *)ob->data;
for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next)
write_bone_animation_matrix(ob, bone);
}
- while (fcu) {
- //for armature animations as objects
- if (ob->type == OB_ARMATURE)
- transformName = fcu->rna_path;
- else
- transformName = extract_transform_name(fcu->rna_path);
-
- if ((STREQ(transformName, "location") || STREQ(transformName, "scale")) ||
- (STREQ(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) ||
- (STREQ(transformName, "rotation_quaternion")))
- {
- dae_animation(ob, fcu, transformName, false);
- }
- fcu = fcu->next;
+ /* Armatures can have object animation and skeletal animation*/
+ if (this->export_settings->sampling_rate < 1) {
+ export_keyframed_animation_set(ob);
+ }
+ else {
+ export_sampled_animation_set(ob);
}
-
}
export_object_constraint_animation(ob);
@@ -93,14 +318,14 @@ void AnimationExporter::operator()(Object *ob)
//Export Lamp parameter animations
if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action) {
- fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
+ FCurve *fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
while (fcu) {
transformName = extract_transform_name(fcu->rna_path);
if ((STREQ(transformName, "color")) || (STREQ(transformName, "spot_size")) ||
(STREQ(transformName, "spot_blend")) || (STREQ(transformName, "distance")))
{
- dae_animation(ob, fcu, transformName, true);
+ create_keyframed_animation(ob, fcu, transformName, true);
}
fcu = fcu->next;
}
@@ -108,7 +333,7 @@ void AnimationExporter::operator()(Object *ob)
//Export Camera parameter animations
if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action) {
- fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
+ FCurve *fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
while (fcu) {
transformName = extract_transform_name(fcu->rna_path);
@@ -117,7 +342,7 @@ void AnimationExporter::operator()(Object *ob)
(STREQ(transformName, "clip_end")) ||
(STREQ(transformName, "clip_start")))
{
- dae_animation(ob, fcu, transformName, true);
+ create_keyframed_animation(ob, fcu, transformName, true);
}
fcu = fcu->next;
}
@@ -129,7 +354,7 @@ void AnimationExporter::operator()(Object *ob)
if (!ma) continue;
if (ma->adt && ma->adt->action) {
/* isMatAnim = true; */
- fcu = (FCurve *)ma->adt->action->curves.first;
+ FCurve *fcu = (FCurve *)ma->adt->action->curves.first;
while (fcu) {
transformName = extract_transform_name(fcu->rna_path);
@@ -137,7 +362,7 @@ void AnimationExporter::operator()(Object *ob)
(STREQ(transformName, "diffuse_color")) || (STREQ(transformName, "alpha")) ||
(STREQ(transformName, "ior")))
{
- dae_animation(ob, fcu, transformName, true, ma);
+ create_keyframed_animation(ob, fcu, transformName, true, ma);
}
fcu = fcu->next;
}
@@ -168,7 +393,7 @@ void AnimationExporter::export_morph_animation(Object *ob)
while (fcu) {
transformName = extract_transform_name(fcu->rna_path);
- dae_animation(ob, fcu, transformName, true);
+ create_keyframed_animation(ob, fcu, transformName, true);
fcu = fcu->next;
}
@@ -201,7 +426,7 @@ void AnimationExporter::make_anim_frames_from_targets(Object *ob, std::vector<fl
obtar = ct->tar;
if (obtar)
- find_frames(obtar, frames);
+ find_keyframes(obtar, frames);
}
if (cti->flush_constraint_targets)
@@ -266,8 +491,8 @@ std::string AnimationExporter::getAnimationPathId(const FCurve *fcu)
return translate_id(rna_path);
}
-//convert f-curves to animation curves and write
-void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma)
+/* convert f-curves to animation curves and write */
+void AnimationExporter::create_keyframed_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma)
{
const char *axis_name = NULL;
char anim_id[200];
@@ -275,6 +500,8 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
bool has_tangents = false;
bool quatRotation = false;
+ Object *obj = NULL;
+
if (STREQ(transformName, "rotation_quaternion") ) {
fprintf(stderr, "quaternion rotation curves are not supported. rotation curve will not be exported\n");
quatRotation = true;
@@ -292,15 +519,26 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
axis_name = axis_names[fcu->array_index];
}
- //axis names for transforms
- else if (STREQ(transformName, "location") ||
- STREQ(transformName, "scale") ||
- STREQ(transformName, "rotation_euler") ||
- STREQ(transformName, "rotation_quaternion"))
+ /*
+ * Note: Handle transformation animations separately (to apply matrix inverse to fcurves)
+ * We will use the object to evaluate the animation on all keyframes and calculate the
+ * resulting object matrix. We need this to incorporate the
+ * effects of the parent inverse matrix (when it contains a rotation component)
+ *
+ * TODO: try to combine exported fcurves into 3 channel animations like done
+ * in export_sampled_animation(). For now each channel is exported as separate <Animation>.
+ */
+
+ else if (
+ STREQ(transformName, "scale") ||
+ STREQ(transformName, "location") ||
+ STREQ(transformName, "rotation_euler"))
{
const char *axis_names[] = {"X", "Y", "Z"};
- if (fcu->array_index < 3)
+ if (fcu->array_index < 3) {
axis_name = axis_names[fcu->array_index];
+ obj = ob;
+ }
}
else {
/* no axis name. single parameter */
@@ -309,7 +547,7 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
std::string ob_name = std::string("null");
- //Create anim Id
+ /* Create anim Id */
if (ob->type == OB_ARMATURE) {
ob_name = getObjectBoneName(ob, fcu);
BLI_snprintf(
@@ -358,7 +596,7 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
output_id = create_lens_source_from_fcurve((Camera *) ob->data, COLLADASW::InputSemantic::OUTPUT, fcu, anim_id);
}
else {
- output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name);
+ output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name, obj);
}
// create interpolations source
@@ -370,10 +608,10 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
if (has_tangents) {
// create in_tangent source
- intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name);
+ intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name, obj);
// create out_tangent source
- outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name);
+ outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name, obj);
}
std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
@@ -476,8 +714,11 @@ void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, B
if (!pchan)
return;
- //every inserted keyframe of bones.
- find_frames(ob_arm, fra);
+
+ if (this->export_settings->sampling_rate < 1)
+ find_keyframes(ob_arm, fra);
+ else
+ find_sampleframes(ob_arm, fra);
if (flag & ARM_RESTPOS) {
arm->flag &= ~ARM_RESTPOS;
@@ -531,7 +772,7 @@ void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_
addSampler(sampler);
- std::string target = get_joint_id(bone, ob_arm) + "/transform";
+ std::string target = get_joint_id(ob_arm, bone) + "/transform";
addChannel(COLLADABU::URI(empty, sampler_id), target);
closeAnimation();
@@ -756,14 +997,60 @@ void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSeman
}
}
+// old function to keep compatibility for calls where offset and object are not needed
std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name)
{
- std::string source_id = anim_id + get_semantic_suffix(semantic);
+ return create_source_from_fcurve(semantic, fcu, anim_id, axis_name, NULL);
+}
- //bool is_angle = STREQ(fcu->rna_path, "rotation");
- bool is_angle = false;
+void AnimationExporter::evaluate_anim_with_constraints(Object *ob, float ctime)
+{
+ BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
+ ListBase *conlist = get_active_constraints(ob);
+ bConstraint *con;
+ for (con = (bConstraint *)conlist->first; con; con = con->next) {
+ ListBase targets = { NULL, NULL };
+
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+
+ if (cti && cti->get_constraint_targets) {
+ bConstraintTarget *ct;
+ Object *obtar;
+ cti->get_constraint_targets(con, &targets);
+ for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
+ obtar = ct->tar;
- if (strstr(fcu->rna_path, "rotation") || strstr(fcu->rna_path,"spot_size")) is_angle = true;
+ if (obtar) {
+ BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM);
+ BKE_object_where_is_calc_time(this->eval_ctx, scene, obtar, ctime);
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 1);
+ }
+ }
+ BKE_object_where_is_calc_time(this->eval_ctx, scene, ob, ctime);
+}
+
+/*
+ * ob is needed to aply parent inverse information to fcurve.
+ * TODO: Here we have to step over all keyframes for each object and for each fcurve.
+ * Instead of processing each fcurve one by one,
+ * step over the animation from keyframe to keyframe,
+ * then create adjusted fcurves (and entries) for all affected objects.
+ * Then we would need to step through the scene only once.
+ */
+std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name, Object *ob)
+{
+ std::string source_id = anim_id + get_semantic_suffix(semantic);
+
+ bool is_angle = (strstr(fcu->rna_path, "rotation") || strstr(fcu->rna_path, "spot_size"));
+ bool is_euler = strstr(fcu->rna_path, "rotation_euler");
+ bool is_translation = strstr(fcu->rna_path, "location");
+ bool is_scale = strstr(fcu->rna_path, "scale");
+ bool is_tangent = false;
+ int offset_index = 0;
COLLADASW::FloatSourceF source(mSW);
source.setId(source_id);
@@ -774,27 +1061,76 @@ std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemanti
case COLLADASW::InputSemantic::INPUT:
case COLLADASW::InputSemantic::OUTPUT:
source.setAccessorStride(1);
+ offset_index = 0;
break;
case COLLADASW::InputSemantic::IN_TANGENT:
case COLLADASW::InputSemantic::OUT_TANGENT:
source.setAccessorStride(2);
+ offset_index = 1;
+ is_tangent = true;
break;
default:
break;
}
-
COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
add_source_parameters(param, semantic, is_angle, axis_name, false);
source.prepareToAppendValues();
- for (unsigned int i = 0; i < fcu->totvert; i++) {
+ for (unsigned int frame_index = 0; frame_index < fcu->totvert; frame_index++) {
+ float fixed_val = 0;
+ if (ob) {
+ float fmat[4][4];
+ float frame = fcu->bezt[frame_index].vec[1][0];
+ float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
+
+ evaluate_anim_with_constraints(ob, ctime); // set object transforms to fcurve's i'th keyframe
+
+ BKE_object_matrix_local_get(ob, fmat);
+ float floc[3];
+ float fquat[4];
+ float fsize[3];
+ mat4_decompose(floc, fquat, fsize, fmat);
+
+ if (is_euler) {
+ float eul[3];
+ quat_to_eul(eul, fquat);
+ fixed_val = RAD2DEGF(eul[fcu->array_index]);
+ }
+ else if (is_translation) {
+ fixed_val = floc[fcu->array_index];
+ }
+ else if (is_scale) {
+ fixed_val = fsize[fcu->array_index];
+ }
+ }
+
float values[3]; // be careful!
+ float offset = 0;
int length = 0;
- get_source_values(&fcu->bezt[i], semantic, is_angle, values, &length);
- for (int j = 0; j < length; j++)
- source.appendValues(values[j]);
+ get_source_values(&fcu->bezt[frame_index], semantic, is_angle, values, &length);
+ if (is_tangent) {
+ float bases[3];
+ int len = 0;
+ get_source_values(&fcu->bezt[frame_index], COLLADASW::InputSemantic::OUTPUT, is_angle, bases, &len);
+ offset = values[offset_index] - bases[0];
+ }
+
+ for (int j = 0; j < length; j++) {
+ float val;
+ if (j == offset_index) {
+ if (ob) {
+ val = fixed_val + offset;
+ }
+ else {
+ val = values[j] + offset;
+ }
+ } else {
+ val = values[j];
+ }
+ source.appendValues(val);
+ }
}
source.finish();
@@ -838,9 +1174,9 @@ std::string AnimationExporter::create_lens_source_from_fcurve(Camera *cam, COLLA
return source_id;
}
-
-
-//Currently called only to get OUTPUT source values ( if rotation and hence the axis is also specified )
+/*
+ * only to get OUTPUT source values ( if rotation and hence the axis is also specified )
+ */
std::string AnimationExporter::create_source_from_array(COLLADASW::InputSemantic::Semantics semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name)
{
std::string source_id = anim_id + get_semantic_suffix(semantic);
@@ -870,7 +1206,10 @@ std::string AnimationExporter::create_source_from_array(COLLADASW::InputSemantic
return source_id;
}
-// only used for sources with INPUT semantic
+
+/*
+ * only used for sources with INPUT semantic
+ */
std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name)
{
std::string source_id = anim_id + get_semantic_suffix(semantic);
@@ -901,9 +1240,47 @@ std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemanti
return source_id;
}
+std::string AnimationExporter::create_4x4_source(std::vector<float> &ctimes, std::vector<float> &values , const std::string &anim_id)
+{
+ COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
+ std::string source_id = anim_id + get_semantic_suffix(semantic);
+
+ COLLADASW::Float4x4Source source(mSW);
+ source.setId(source_id);
+ source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+ source.setAccessorCount(ctimes.size());
+ source.setAccessorStride(16);
+
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ add_source_parameters(param, semantic, false, NULL, true);
+
+ source.prepareToAppendValues();
+
+ std::vector<float>::iterator it;
+
+ for (it = values.begin(); it != values.end(); it+=16) {
+ float mat[4][4];
+
+ bc_copy_m4_farray(mat, &*it);
+
+ UnitConverter converter;
+ double outmat[4][4];
+ converter.mat4_to_dae_double(outmat, mat);
+
+ if (this->export_settings->limit_precision)
+ bc_sanitize_mat(outmat, 6);
+
+ source.appendValues(outmat);
+ }
+
+ source.finish();
+ return source_id;
+}
std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob, Bone *bone, const std::string &anim_id)
{
+ bool is_bone_animation = ob->type == OB_ARMATURE && bone;
+
COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
std::string source_id = anim_id + get_semantic_suffix(semantic);
@@ -921,7 +1298,7 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
bPoseChannel *parchan = NULL;
bPoseChannel *pchan = NULL;
- if (ob->type == OB_ARMATURE && bone) {
+ if (is_bone_animation) {
bPose *pose = ob->pose;
pchan = BKE_pose_channel_find_name(pose, bone->name);
if (!pchan)
@@ -936,13 +1313,12 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
int j = 0;
for (it = frames.begin(); it != frames.end(); it++) {
float mat[4][4], ipar[4][4];
+ float frame = *it;
+
+ float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
+ bc_update_scene(eval_ctx, scene, ctime);
+ if (is_bone_animation) {
- float ctime = BKE_scene_frame_get_from_ctime(scene, *it);
- CFRA = BKE_scene_frame_get_from_ctime(scene, *it);
- //BKE_scene_graph_update_for_newframe(G.main->eval_ctx, depsgraph, G.main,scene);
- BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
-
- if (bone) {
if (pchan->flag & POSE_CHAIN) {
enable_fcurves(ob->adt->action, NULL);
BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
@@ -960,9 +1336,10 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
else
copy_m4_m4(mat, pchan->pose_mat);
- // OPEN_SIM_COMPATIBILITY
- // AFAIK animation to second life is via BVH, but no
- // reason to not have the collada-animation be correct
+ /* OPEN_SIM_COMPATIBILITY
+ * AFAIK animation to second life is via BVH, but no
+ * reason to not have the collada-animation be correct
+ */
if (export_settings->open_sim) {
float temp[4][4];
copy_m4_m4(temp, bone->arm_mat);
@@ -981,7 +1358,7 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
}
else {
- calc_ob_mat_at_time(ob, ctime, mat);
+ copy_m4_m4(mat, ob->obmat);
}
UnitConverter converter;
@@ -989,6 +1366,9 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
double outmat[4][4];
converter.mat4_to_dae_double(outmat, mat);
+ if (this->export_settings->limit_precision)
+ bc_sanitize_mat(outmat, 6);
+
source.appendValues(outmat);
j++;
@@ -1006,7 +1386,9 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
}
-// only used for sources with OUTPUT semantic ( locations and scale)
+/*
+ * only used for sources with OUTPUT semantic ( locations and scale)
+ */
std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id)
{
COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
@@ -1190,8 +1572,10 @@ std::string AnimationExporter::get_camera_param_sid(char *rna_path, int tm_type,
return std::string("");
}
-// Assign sid of the animated parameter or transform
-// for rotation, axis name is always appended and the value of append_axis is ignored
+/*
+ * Assign sid of the animated parameter or transform for rotation,
+ * axis name is always appended and the value of append_axis is ignored
+ */
std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
{
std::string tm_name;
@@ -1275,29 +1659,10 @@ char *AnimationExporter::extract_transform_name(char *rna_path)
return dot ? (dot + 1) : rna_path;
}
-//find keyframes of all the objects animations
-void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra)
-{
- if (ob->adt && ob->adt->action) {
- FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
-
- for (; fcu; fcu = fcu->next) {
- for (unsigned int i = 0; i < fcu->totvert; i++) {
- float f = fcu->bezt[i].vec[1][0];
- if (std::find(fra.begin(), fra.end(), f) == fra.end())
- fra.push_back(f);
- }
- }
-
- // keep the keys in ascending order
- std::sort(fra.begin(), fra.end());
- }
-}
-
-
-
-// enable fcurves driving a specific bone, disable all the rest
-// if bone_name = NULL enable all fcurves
+/*
+ * enable fcurves driving a specific bone, disable all the rest
+ * if bone_name = NULL enable all fcurves
+ */
void AnimationExporter::enable_fcurves(bAction *act, char *bone_name)
{
FCurve *fcu;
@@ -1362,14 +1727,53 @@ bool AnimationExporter::hasAnimations(Scene *sce)
void AnimationExporter::find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)
{
if (rotmode > 0)
- find_frames(ob, fra, prefix, "rotation_euler");
+ find_keyframes(ob, fra, prefix, "rotation_euler");
else if (rotmode == ROT_MODE_QUAT)
- find_frames(ob, fra, prefix, "rotation_quaternion");
+ find_keyframes(ob, fra, prefix, "rotation_quaternion");
/*else if (rotmode == ROT_MODE_AXISANGLE)
;*/
}
-void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
+/* Take care to always have the first frame and the last frame in the animation
+ * regardless of the sampling_rate setting
+ */
+void AnimationExporter::find_sampleframes(Object *ob, std::vector<float> &fra)
+{
+ int frame = scene->r.sfra;
+ do {
+ float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
+ fra.push_back(ctime);
+ if (frame == scene->r.efra)
+ break;
+ frame += this->export_settings->sampling_rate;
+ if (frame > scene->r.efra)
+ frame = scene->r.efra; // make sure the last frame is always exported
+
+ } while (true);
+}
+
+/*
+ * find keyframes of all the objects animations
+ */
+void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra)
+{
+ if (ob->adt && ob->adt->action) {
+ FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
+
+ for (; fcu; fcu = fcu->next) {
+ for (unsigned int i = 0; i < fcu->totvert; i++) {
+ float f = fcu->bezt[i].vec[1][0];
+ if (std::find(fra.begin(), fra.end(), f) == fra.end())
+ fra.push_back(f);
+ }
+ }
+
+ // keep the keys in ascending order
+ std::sort(fra.begin(), fra.end());
+ }
+}
+
+void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
{
if (ob->adt && ob->adt->action) {
FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
@@ -1427,10 +1831,10 @@ void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bo
find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode);
break;
case 1:
- find_frames(ob_arm, fra, prefix, "scale");
+ find_keyframes(ob_arm, fra, prefix, "scale");
break;
case 2:
- find_frames(ob_arm, fra, prefix, "location");
+ find_keyframes(ob_arm, fra, prefix, "location");
break;
default:
return;
@@ -1524,46 +1928,21 @@ void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, i
bool AnimationExporter::validateConstraints(bConstraint *con)
{
- bool valid = true;
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
/* these we can skip completely (invalid constraints...) */
- if (cti == NULL) valid = false;
- if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) valid = false;
- /* these constraints can't be evaluated anyway */
- if (cti->evaluate_constraint == NULL) valid = false;
- /* influence == 0 should be ignored */
- if (con->enforce == 0.0f) valid = false;
-
- return valid;
-}
+ if (cti == NULL)
+ return false;
+ if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF))
+ return false;
-void AnimationExporter::calc_ob_mat_at_time(Object *ob, float ctime , float mat[][4])
-{
- ListBase *conlist = get_active_constraints(ob);
- bConstraint *con;
- for (con = (bConstraint *)conlist->first; con; con = con->next) {
- ListBase targets = {NULL, NULL};
-
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
-
- if (cti && cti->get_constraint_targets) {
- bConstraintTarget *ct;
- Object *obtar;
- cti->get_constraint_targets(con, &targets);
- for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
- obtar = ct->tar;
+ /* these constraints can't be evaluated anyway */
+ if (cti->evaluate_constraint == NULL)
+ return false;
- if (obtar) {
- BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM);
- BKE_object_where_is_calc_time(eval_ctx, scene, obtar, ctime);
- }
- }
+ /* influence == 0 should be ignored */
+ if (con->enforce == 0.0f)
+ return false;
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
- }
- BKE_object_where_is_calc_time(eval_ctx, scene, ob, ctime);
- copy_m4_m4(mat, ob->obmat);
+ /* validation passed */
+ return true;
}
-
diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h
index 5af5d884455..d2216c04ee5 100644
--- a/source/blender/collada/AnimationExporter.h
+++ b/source/blender/collada/AnimationExporter.h
@@ -85,25 +85,26 @@ class AnimationExporter: COLLADASW::LibraryAnimations
{
private:
Scene *scene;
- const struct EvaluationContext *eval_ctx;
+ EvaluationContext *eval_ctx;
COLLADASW::StreamWriter *sw;
public:
- AnimationExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings):
- COLLADASW::LibraryAnimations(sw), export_settings(export_settings)
- { this->sw = sw; }
-
-
- bool exportAnimations(const struct EvaluationContext *eval_ctx, Scene *sce);
+ AnimationExporter(EvaluationContext *eval_ctx, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings):
+ eval_ctx(eval_ctx),
+ COLLADASW::LibraryAnimations(sw),
+ export_settings(export_settings)
+ {
+ this->sw = sw;
+ }
+ bool exportAnimations(Scene *sce);
// called for each exported object
void operator() (Object *ob);
protected:
const ExportSettings *export_settings;
- void dae_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma = NULL);
void export_object_constraint_animation(Object *ob);
@@ -144,7 +145,18 @@ protected:
float* get_eul_source_for_quat(Object *ob );
+ bool is_flat_line(std::vector<float> &values, int channel_count);
+ void export_keyframed_animation_set(Object *ob);
+ void create_keyframed_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma = NULL);
+ void export_sampled_animation_set(Object *ob);
+ void export_sampled_transrotloc_animation(Object *ob, std::vector<float> &ctimes);
+ void export_sampled_matrix_animation(Object *ob, std::vector<float> &ctimes);
+ void create_sampled_animation(int channel_count, std::vector<float> &times, std::vector<float> &values, std::string, std::string label, std::string axis_name, bool is_rot);
+
+ void evaluate_anim_with_constraints(Object *ob, float ctime);
+
std::string create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name);
+ std::string create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name, Object *ob);
std::string create_lens_source_from_fcurve(Camera *cam, COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id);
@@ -153,7 +165,7 @@ protected:
std::string create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name);
std::string create_xyz_source(float *v, int tot, const std::string& anim_id);
-
+ std::string create_4x4_source(std::vector<float> &times, std::vector<float> &values, const std::string& anim_id);
std::string create_4x4_source(std::vector<float> &frames, Object * ob_arm, Bone *bone, const std::string& anim_id);
std::string create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents);
@@ -165,8 +177,10 @@ protected:
std::string get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis);
std::string get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis);
- void find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name);
- void find_frames(Object *ob, std::vector<float> &fra);
+ void find_keyframes(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name);
+ void find_keyframes(Object *ob, std::vector<float> &fra);
+ void find_sampleframes(Object *ob, std::vector<float> &fra);
+
void make_anim_frames_from_targets(Object *ob, std::vector<float> &frames );
@@ -187,6 +201,5 @@ protected:
bool validateConstraints(bConstraint *con);
- void calc_ob_mat_at_time(Object *ob, float ctime , float mat[][4]);
};
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index 65acce41046..b12ecb50e32 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -70,14 +70,15 @@ FCurve *AnimationImporter::create_fcurve(int array_index, const char *rna_path)
fcu->array_index = array_index;
return fcu;
}
-
-void AnimationImporter::create_bezt(FCurve *fcu, float frame, float output)
+
+void AnimationImporter::add_bezt(FCurve *fcu, float frame, float value, eBezTriple_Interpolation ipo)
{
+ //float fps = (float)FPS;
BezTriple bez;
memset(&bez, 0, sizeof(BezTriple));
bez.vec[1][0] = frame;
- bez.vec[1][1] = output;
- bez.ipo = U.ipo_new; /* use default interpolation mode here... */
+ bez.vec[1][1] = value;
+ bez.ipo = ipo; /* use default interpolation mode here... */
bez.f1 = bez.f2 = bez.f3 = SELECT;
bez.h1 = bez.h2 = HD_AUTO;
insert_bezt_fcurve(fcu, &bez, 0);
@@ -108,7 +109,7 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED);
// fcu->rna_path = BLI_strdupn(path, strlen(path));
fcu->array_index = 0;
- fcu->totvert = curve->getKeyCount();
+ //fcu->totvert = curve->getKeyCount();
// create beztriple for each key
for (unsigned int j = 0; j < curve->getKeyCount(); j++) {
@@ -401,7 +402,7 @@ virtual void AnimationImporter::change_eul_to_quat(Object *ob, bAction *act)
eul_to_quat(quat, eul);
for (int k = 0; k < 4; k++)
- create_bezt(quatcu[k], frame, quat[k]);
+ create_bezt(quatcu[k], frame, quat[k], U.ipo_new);
}
}
@@ -591,6 +592,12 @@ void AnimationImporter:: Assign_color_animations(const COLLADAFW::UniqueId& list
BLI_strncpy(rna_path, anim_type, sizeof(rna_path));
const COLLADAFW::AnimationList *animlist = animlist_map[listid];
+ if (animlist == NULL)
+ {
+ fprintf(stderr, "Collada: No animlist found for ID: %s of type %s\n", listid.toAscii().c_str(), anim_type);
+ return;
+ }
+
const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
//all the curves belonging to the current binding
std::vector<FCurve *> animcurves;
@@ -668,6 +675,13 @@ void AnimationImporter:: Assign_float_animations(const COLLADAFW::UniqueId& list
}
+float AnimationImporter::convert_to_focal_length(float in_xfov, int fov_type, float aspect, float sensorx)
+{
+ // NOTE: Needs more testing (As we curretnly have no official test data for this)
+ float xfov = (fov_type == CAMERA_YFOV) ? (2.0f * atanf(aspect * tanf(DEG2RADF(in_xfov) * 0.5f))) : DEG2RADF(in_xfov);
+ return fov_to_focallength(xfov, sensorx);
+}
+
/*
* Lens animations must be stored in COLLADA by using FOV,
* while blender internally uses focal length.
@@ -697,13 +711,9 @@ void AnimationImporter::Assign_lens_animations(const COLLADAFW::UniqueId& listid
FCurve *fcu = *iter;
for (unsigned int i = 0; i < fcu->totvert; i++) {
-
- double input_fov = fcu->bezt[i].vec[1][1];
-
- // NOTE: Needs more testing (As we curretnly have no official test data for this)
- double xfov = (fov_type == CAMERA_YFOV) ? (2.0f * atanf(aspect * tanf(DEG2RADF(input_fov) * 0.5f))) : DEG2RADF(input_fov);
-
- fcu->bezt[i].vec[1][1] = fov_to_focallength(xfov, cam->sensor_x);
+ fcu->bezt[i].vec[0][1] = convert_to_focal_length(fcu->bezt[i].vec[0][1], fov_type, aspect, cam->sensor_x);
+ fcu->bezt[i].vec[1][1] = convert_to_focal_length(fcu->bezt[i].vec[1][1], fov_type, aspect, cam->sensor_x);
+ fcu->bezt[i].vec[2][1] = convert_to_focal_length(fcu->bezt[i].vec[2][1], fov_type, aspect, cam->sensor_x);
}
BLI_addtail(AnimCurves, fcu);
@@ -764,7 +774,6 @@ void AnimationImporter::apply_matrix_curves(Object *ob, std::vector<FCurve *>& a
axis = i - 7;
}
-
if (is_joint)
BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str);
else
@@ -780,6 +789,9 @@ void AnimationImporter::apply_matrix_curves(Object *ob, std::vector<FCurve *>& a
std::vector<float>::iterator it;
+ //float qref[4];
+ //unit_qt(qref);
+
// sample values at each frame
for (it = frames.begin(); it != frames.end(); it++) {
float fra = *it;
@@ -814,15 +826,7 @@ void AnimationImporter::apply_matrix_curves(Object *ob, std::vector<FCurve *>& a
}
float rot[4], loc[3], scale[3];
-
- mat4_to_quat(rot, mat);
-#if 0
- for (int i = 0 ; i < 4; i++) {
- rot[i] = RAD2DEGF(rot[i]);
- }
-#endif
- copy_v3_v3(loc, mat[3]);
- mat4_to_size(scale, mat);
+ mat4_decompose(loc, rot, scale, mat);
// add keys
for (int i = 0; i < totcu; i++) {
@@ -891,11 +895,22 @@ static const double get_aspect_ratio(const COLLADAFW::Camera *camera)
return aspect;
}
+static ListBase &get_animation_curves(Material *ma)
+{
+ bAction *act;
+ if (!ma->adt || !ma->adt->action)
+ act = verify_adt_action((ID *)&ma->id, 1);
+ else
+ act = ma->adt->action;
+
+ return act->curves;
+}
void AnimationImporter::translate_Animations(COLLADAFW::Node *node,
std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& root_map,
std::multimap<COLLADAFW::UniqueId, Object *>& object_map,
- std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map)
+ std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map,
+ std::map<COLLADAFW::UniqueId, Material*> uid_material_map)
{
bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
COLLADAFW::UniqueId uid = node->getUniqueId();
@@ -1073,11 +1088,6 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node,
}
}
if (animType->material != 0) {
- Material *ma = give_current_material(ob, 1);
- if (!ma->adt || !ma->adt->action) act = verify_adt_action((ID *)&ma->id, 1);
- else act = ma->adt->action;
-
- ListBase *AnimCurves = &(act->curves);
const COLLADAFW::InstanceGeometryPointerArray& nodeGeoms = node->getInstanceGeometries();
for (unsigned int i = 0; i < nodeGeoms.getCount(); i++) {
@@ -1086,30 +1096,36 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node,
const COLLADAFW::UniqueId & matuid = matBinds[j].getReferencedMaterial();
const COLLADAFW::Effect *ef = (COLLADAFW::Effect *) (FW_object_map[matuid]);
if (ef != NULL) { /* can be NULL [#28909] */
- const COLLADAFW::CommonEffectPointerArray& commonEffects = ef->getCommonEffects();
+ Material *ma = uid_material_map[matuid];
+ if (!ma) {
+ fprintf(stderr, "Collada: Node %s refers to undefined material\n", node->getName().c_str());
+ continue;
+ }
+ ListBase &AnimCurves = get_animation_curves(ma);
+ const COLLADAFW::CommonEffectPointerArray& commonEffects = ef->getCommonEffects();
COLLADAFW::EffectCommon *efc = commonEffects[0];
if ((animType->material & MATERIAL_SHININESS) != 0) {
const COLLADAFW::FloatOrParam *shin = &(efc->getShininess());
- const COLLADAFW::UniqueId& listid = shin->getAnimationList();
- Assign_float_animations(listid, AnimCurves, "specular_hardness");
+ const COLLADAFW::UniqueId& listid = shin->getAnimationList();
+ Assign_float_animations(listid, &AnimCurves, "specular_hardness");
}
if ((animType->material & MATERIAL_IOR) != 0) {
const COLLADAFW::FloatOrParam *ior = &(efc->getIndexOfRefraction());
- const COLLADAFW::UniqueId& listid = ior->getAnimationList();
- Assign_float_animations(listid, AnimCurves, "raytrace_transparency.ior");
+ const COLLADAFW::UniqueId& listid = ior->getAnimationList();
+ Assign_float_animations(listid, &AnimCurves, "raytrace_transparency.ior");
}
if ((animType->material & MATERIAL_SPEC_COLOR) != 0) {
const COLLADAFW::ColorOrTexture *cot = &(efc->getSpecular());
- const COLLADAFW::UniqueId& listid = cot->getColor().getAnimationList();
- Assign_color_animations(listid, AnimCurves, "specular_color");
+ const COLLADAFW::UniqueId& listid = cot->getColor().getAnimationList();
+ Assign_color_animations(listid, &AnimCurves, "specular_color");
}
if ((animType->material & MATERIAL_DIFF_COLOR) != 0) {
const COLLADAFW::ColorOrTexture *cot = &(efc->getDiffuse());
- const COLLADAFW::UniqueId& listid = cot->getColor().getAnimationList();
- Assign_color_animations(listid, AnimCurves, "diffuse_color");
+ const COLLADAFW::UniqueId& listid = cot->getColor().getAnimationList();
+ Assign_color_animations(listid, &AnimCurves, "diffuse_color");
}
}
}
@@ -1190,6 +1206,9 @@ void AnimationImporter::add_bone_animation_sampled(Object *ob, std::vector<FCurv
std::sort(frames.begin(), frames.end());
+ float qref[4];
+ unit_qt(qref);
+
std::vector<float>::iterator it;
// sample values at each frame
@@ -1223,7 +1242,9 @@ void AnimationImporter::add_bone_animation_sampled(Object *ob, std::vector<FCurv
float rot[4], loc[3], scale[3];
- mat4_to_quat(rot, mat);
+ bc_rotate_from_reference_quat(rot, qref, mat);
+ copy_qt_qt(qref, rot);
+
copy_v3_v3(loc, mat[3]);
mat4_to_size(scale, mat);
@@ -1561,7 +1582,8 @@ Object *AnimationImporter::translate_animation_OLD(COLLADAFW::Node *node,
copy_m4_m4(mat, matfra);
}
- float val[4], rot[4], loc[3], scale[3];
+ float val[4] = {};
+ float rot[4], loc[3], scale[3];
switch (tm_type) {
case COLLADAFW::Transformation::ROTATE:
@@ -1833,23 +1855,18 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, float
}
COLLADABU::Math::Matrix4 matrix;
- int i = 0, j = 0;
+ int mi = 0, mj = 0;
for (std::vector<FCurve *>::iterator it = curves.begin(); it != curves.end(); it++) {
- matrix.setElement(i, j, evaluate_fcurve(*it, fra));
- j++;
- if (j == 4) {
- i++;
- j = 0;
+ matrix.setElement(mi, mj, evaluate_fcurve(*it, fra));
+ mj++;
+ if (mj == 4) {
+ mi++;
+ mj = 0;
}
fcurve_is_used(*it);
}
-
- COLLADAFW::Matrix tm(matrix);
- dae_matrix_to_mat4(&tm, mat);
-
- std::vector<FCurve *>::iterator it;
-
+ unit_converter->dae_matrix_to_mat4_(mat, matrix);
return true;
}
}
@@ -2012,19 +2029,6 @@ void AnimationImporter::add_bone_fcurve(Object *ob, COLLADAFW::Node *node, FCurv
action_groups_add_channel(act, grp, fcu);
}
-void AnimationImporter::add_bezt(FCurve *fcu, float fra, float value)
-{
- //float fps = (float)FPS;
- BezTriple bez;
- memset(&bez, 0, sizeof(BezTriple));
- bez.vec[1][0] = fra;
- bez.vec[1][1] = value;
- bez.ipo = BEZT_IPO_LIN; /* use default interpolation mode here... */
- bez.f1 = bez.f2 = bez.f3 = SELECT;
- bez.h1 = bez.h2 = HD_AUTO;
- insert_bezt_fcurve(fcu, &bez, 0);
- calchandles_fcurve(fcu);
-}
void AnimationImporter::set_import_from_version(std::string import_from_version)
{
diff --git a/source/blender/collada/AnimationImporter.h b/source/blender/collada/AnimationImporter.h
index 15dee8ff5f4..e25116cac9f 100644
--- a/source/blender/collada/AnimationImporter.h
+++ b/source/blender/collada/AnimationImporter.h
@@ -78,7 +78,7 @@ private:
FCurve *create_fcurve(int array_index, const char *rna_path);
- void create_bezt(FCurve *fcu, float frame, float output);
+ void add_bezt(FCurve *fcu, float frame, float value, eBezTriple_Interpolation ipo=BEZT_IPO_LIN);
// create one or several fcurves depending on the number of parameters being animated
void animation_to_fcurves(COLLADAFW::AnimationCurve *curve);
@@ -156,7 +156,8 @@ public:
void translate_Animations(COLLADAFW::Node * Node,
std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
std::multimap<COLLADAFW::UniqueId, Object*>& object_map,
- std::map<COLLADAFW::UniqueId, const COLLADAFW::Object*> FW_object_map);
+ std::map<COLLADAFW::UniqueId, const COLLADAFW::Object*> FW_object_map,
+ std::map<COLLADAFW::UniqueId, Material*> uid_material_map);
AnimMix* get_animation_type( const COLLADAFW::Node * node, std::map<COLLADAFW::UniqueId, const COLLADAFW::Object*> FW_object_map );
@@ -202,6 +203,8 @@ public:
// gives a world-space mat, end's mat not included
bool calc_joint_parent_mat_rest(float mat[4][4], float par[4][4], COLLADAFW::Node *node, COLLADAFW::Node *end);
+ float convert_to_focal_length(float in_xfov, int fov_type, float aspect, float sensorx);
+
#ifdef ARMATURE_TEST
Object *get_joint_object(COLLADAFW::Node *root, COLLADAFW::Node *node, Object *par_job);
#endif
@@ -214,8 +217,6 @@ public:
void add_bone_fcurve(Object *ob, COLLADAFW::Node *node, FCurve *fcu);
- void add_bezt(FCurve *fcu, float fra, float value);
-
void extra_data_importer(std::string elementName);
};
diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp
index 844be2dd60b..fbceb6e077f 100644
--- a/source/blender/collada/ArmatureExporter.cpp
+++ b/source/blender/collada/ArmatureExporter.cpp
@@ -89,7 +89,7 @@ void ArmatureExporter::add_armature_bones(const EvaluationContext *eval_ctx, Obj
void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone)
{
if (bc_is_root_bone(bone, this->export_settings->deform_bones_only))
- ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(bone, ob_arm)));
+ ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(ob_arm, bone)));
else {
for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
write_bone_URLs(ins, ob_arm, child);
@@ -162,9 +162,9 @@ void ArmatureExporter::add_bone_node(const EvaluationContext *eval_ctx, Bone *bo
std::list<Object *>& child_objects)
{
if (!(this->export_settings->deform_bones_only && bone->flag & BONE_NO_DEFORM)) {
- std::string node_id = get_joint_id(bone, ob_arm);
+ std::string node_id = get_joint_id(ob_arm, bone);
std::string node_name = std::string(bone->name);
- std::string node_sid = get_joint_sid(bone, ob_arm);
+ std::string node_sid = get_joint_sid(bone);
COLLADASW::Node node(mSW);
diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp
index 8832e0fd577..b2794b3bd23 100644
--- a/source/blender/collada/ArmatureImporter.cpp
+++ b/source/blender/collada/ArmatureImporter.cpp
@@ -284,12 +284,11 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone
BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(armature);
BoneExtended *dominant_child = NULL;
int maxlen = 0;
- Bone *child;
if (parentbone == NULL)
return;
- child = (Bone *)parentbone->childbase.first;
+ Bone *child = (Bone *)parentbone->childbase.first;
if (child && (import_settings->find_chains || child->next==NULL)) {
for (; child; child = child->next) {
BoneExtended *be = extended_bones[child->name];
@@ -339,8 +338,8 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone
}
}
}
- for (Bone *child = (Bone *)parentbone->childbase.first; child; child = child->next) {
- ArmatureImporter::connect_bone_chains(armature, child, UNLIMITED_CHAIN_MAX);
+ for (Bone *ch = (Bone *)parentbone->childbase.first; ch; ch = ch->next) {
+ ArmatureImporter::connect_bone_chains(armature, ch, UNLIMITED_CHAIN_MAX);
}
}
else if (maxlen>1 && maxlen > this->import_settings->min_chain_length) {
@@ -350,8 +349,8 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone
else {
/* can't connect this Bone. Proceed with children ... */
if (pbe) pbe->set_leaf_bone(true);
- for (Bone *child = (Bone *)parentbone->childbase.first; child; child = child->next) {
- ArmatureImporter::connect_bone_chains(armature, child, UNLIMITED_CHAIN_MAX);
+ for (Bone *ch = (Bone *)parentbone->childbase.first; ch; ch = ch->next) {
+ ArmatureImporter::connect_bone_chains(armature, ch, UNLIMITED_CHAIN_MAX);
}
}
diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp
index f413651167c..f32cb624f78 100644
--- a/source/blender/collada/ControllerExporter.cpp
+++ b/source/blender/collada/ControllerExporter.cpp
@@ -71,7 +71,7 @@ bool ControllerExporter::is_skinned_mesh(Object *ob)
void ControllerExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone)
{
if (bc_is_root_bone(bone, this->export_settings->deform_bones_only))
- ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(bone, ob_arm)));
+ ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(ob_arm, bone)));
else {
for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
write_bone_URLs(ins, ob_arm, child);
@@ -280,7 +280,7 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
}
if (oob_counter > 0) {
- fprintf(stderr, "Ignored %d Vertex weights which use index to non existing VGroup %lu.\n",
+ fprintf(stderr, "Ignored %d Vertex weights which use index to non existing VGroup %zu.\n",
oob_counter, joint_index_by_def_index.size());
}
}
@@ -456,7 +456,7 @@ std::string ControllerExporter::add_joints_source(Object *ob_arm, ListBase *defb
for (def = (bDeformGroup *)defbase->first; def; def = def->next) {
Bone *bone = get_bone_from_defgroup(ob_arm, def);
if (bone)
- source.appendValues(get_joint_sid(bone, ob_arm));
+ source.appendValues(get_joint_sid(bone));
}
source.finish();
diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp
index ce0c52cdcd1..04af73f2406 100644
--- a/source/blender/collada/DocumentExporter.cpp
+++ b/source/blender/collada/DocumentExporter.cpp
@@ -152,7 +152,9 @@ char *bc_CustomData_get_active_layer_name(const CustomData *data, int type)
return data->layers[layer_index].name;
}
-DocumentExporter::DocumentExporter(const ExportSettings *export_settings) : export_settings(export_settings) {
+DocumentExporter::DocumentExporter(EvaluationContext *eval_ctx, const ExportSettings *export_settings) :
+ eval_ctx(eval_ctx),
+ export_settings(export_settings) {
}
static COLLADABU::NativeString make_temp_filepath(const char *name, const char *extension)
@@ -179,7 +181,8 @@ static COLLADABU::NativeString make_temp_filepath(const char *name, const char *
// COLLADA allows this through multiple <channel>s in <animation>.
// For this to work, we need to know objects that use a certain action.
-int DocumentExporter::exportCurrentScene(const EvaluationContext *eval_ctx, Scene *sce)
+
+int DocumentExporter::exportCurrentScene(Scene *sce)
{
PointerRNA sceneptr, unit_settings;
PropertyRNA *system; /* unused , *scale; */
@@ -299,29 +302,12 @@ int DocumentExporter::exportCurrentScene(const EvaluationContext *eval_ctx, Scen
// <library_visual_scenes>
SceneExporter se(writer, &arm_exporter, this->export_settings);
-#if 0
- /* The following code seems to be an obsolete workaround
- Comment out until it proofs correct that we no longer need it.
- */
-
- // <library_animations>
- AnimationExporter ae(writer, this->export_settings);
- bool has_animations = ae.exportAnimations(eval_ctx, sce);
-
- if (has_animations && this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) {
- // channels adressing <matrix> objects is not (yet) supported
- // So we force usage of <location>, <translation> and <scale>
- fprintf(stdout,
- "For animated Ojects we must use decomposed <matrix> elements,\n" \
- "Forcing usage of TransLocRot transformation type.");
- se.setExportTransformationType(BC_TRANSFORMATION_TYPE_TRANSROTLOC);
- }
- else {
- se.setExportTransformationType(this->export_settings->export_transformation_type);
+
+ if (this->export_settings->include_animations) {
+ // <library_animations>
+ AnimationExporter ae(eval_ctx, writer, this->export_settings);
+ ae.exportAnimations(sce);
}
-#else
- se.setExportTransformationType(this->export_settings->export_transformation_type);
-#endif
se.exportScene(eval_ctx, sce);
// <scene>
diff --git a/source/blender/collada/DocumentExporter.h b/source/blender/collada/DocumentExporter.h
index 895787c7bbc..68e1523fbee 100644
--- a/source/blender/collada/DocumentExporter.h
+++ b/source/blender/collada/DocumentExporter.h
@@ -27,10 +27,11 @@
#ifndef __DOCUMENTEXPORTER_H__
#define __DOCUMENTEXPORTER_H__
-#include "ExportSettings.h"
+#include "collada.h"
extern "C" {
#include "DNA_customdata_types.h"
+
}
struct Scene;
@@ -38,11 +39,13 @@ struct Scene;
class DocumentExporter
{
public:
- DocumentExporter(const ExportSettings *export_settings);
- int exportCurrentScene(const struct EvaluationContext *eval_ctx, Scene *sce);
+ DocumentExporter(EvaluationContext *eval_ctx, const ExportSettings *export_settings);
+ int exportCurrentScene(Scene *sce);
+
void exportScenes(const char *filename);
private:
const ExportSettings *export_settings;
+ EvaluationContext *eval_ctx;
};
#endif
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index dfd662aa66c..97b11f72509 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -195,8 +195,8 @@ void DocumentImporter::finish()
std::vector<Object *> *objects_to_scale = new std::vector<Object *>();
/** TODO Break up and put into 2-pass parsing of DAE */
- std::vector<const COLLADAFW::VisualScene *>::iterator it;
- for (it = vscenes.begin(); it != vscenes.end(); it++) {
+ std::vector<const COLLADAFW::VisualScene *>::iterator sit;
+ for (sit = vscenes.begin(); sit != vscenes.end(); sit++) {
PointerRNA sceneptr, unit_settings;
PropertyRNA *system, *scale;
@@ -227,7 +227,7 @@ void DocumentImporter::finish()
}
// Write nodes to scene
- const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
+ const COLLADAFW::NodePointerArray& roots = (*sit)->getRootNodes();
for (unsigned int i = 0; i < roots.getCount(); i++) {
std::vector<Object *> *objects_done = write_node(roots[i], NULL, sce, NULL, false);
objects_to_scale->insert(objects_to_scale->end(), objects_done->begin(), objects_done->end());
@@ -252,8 +252,8 @@ void DocumentImporter::finish()
armature_importer.fix_animation();
#endif
- for (std::vector<const COLLADAFW::VisualScene *>::iterator it = vscenes.begin(); it != vscenes.end(); it++) {
- const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
+ for (std::vector<const COLLADAFW::VisualScene *>::iterator vsit = vscenes.begin(); vsit != vscenes.end(); vsit++) {
+ const COLLADAFW::NodePointerArray& roots = (*vsit)->getRootNodes();
for (unsigned int i = 0; i < roots.getCount(); i++) {
translate_anim_recursive(roots[i], NULL, NULL);
@@ -261,7 +261,6 @@ void DocumentImporter::finish()
}
if (libnode_ob.size()) {
- Scene *sce = CTX_data_scene(mContext);
fprintf(stderr, "got %d library nodes to free\n", (int)libnode_ob.size());
// free all library_nodes
@@ -318,7 +317,7 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW
translate_anim_recursive(node, node, parob);
}
else {
- anim_importer.translate_Animations(node, root_map, object_map, FW_object_map);
+ anim_importer.translate_Animations(node, root_map, object_map, FW_object_map, uid_material_map);
COLLADAFW::NodePointerArray &children = node->getChildNodes();
for (i = 0; i < children.getCount(); i++) {
translate_anim_recursive(children[i], node, NULL);
@@ -472,9 +471,9 @@ void DocumentImporter::create_constraints(ExtraTags *et, Object *ob)
{
if (et && et->isProfile("blender")) {
std::string name;
- short* type = 0;
- et->setData("type", type);
- BKE_constraint_add_for_object(ob, "Test_con", *type);
+ short type = 0;
+ et->setData("type", &type);
+ BKE_constraint_add_for_object(ob, "Test_con", type);
}
}
@@ -585,8 +584,8 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
++lamp_done;
}
while (controller_done < controller.getCount()) {
- COLLADAFW::InstanceGeometry *geom = (COLLADAFW::InstanceGeometry *)controller[controller_done];
- ob = mesh_importer.create_mesh_object(node, geom, true, uid_material_map, material_texture_mapping_map);
+ COLLADAFW::InstanceGeometry *geometry = (COLLADAFW::InstanceGeometry *)controller[controller_done];
+ ob = mesh_importer.create_mesh_object(node, geometry, true, uid_material_map, material_texture_mapping_map);
if (ob == NULL) {
report_unknown_reference(*node, "instance_controller");
}
diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp
index 5e7f92047d3..5e2b00be82a 100644
--- a/source/blender/collada/EffectExporter.cpp
+++ b/source/blender/collada/EffectExporter.cpp
@@ -67,7 +67,7 @@ EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettin
bool EffectsExporter::hasEffects(Scene *sce)
{
- FOREACH_SCENE_OBJECT(sce, ob)
+ FOREACH_SCENE_OBJECT_BEGIN(sce, ob)
{
int a;
for (a = 0; a < ob->totcol; a++) {
@@ -79,7 +79,7 @@ bool EffectsExporter::hasEffects(Scene *sce)
return true;
}
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
return false;
}
diff --git a/source/blender/collada/ErrorHandler.cpp b/source/blender/collada/ErrorHandler.cpp
index 32aa5636e08..7e18328f000 100644
--- a/source/blender/collada/ErrorHandler.cpp
+++ b/source/blender/collada/ErrorHandler.cpp
@@ -49,7 +49,10 @@ ErrorHandler::~ErrorHandler()
//--------------------------------------------------------------------
bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
{
- bool isError = false;
+ /* This method must return true when Collada should continue.
+ See https://github.com/KhronosGroup/OpenCOLLADA/issues/442
+ */
+ bool isWarning = false;
if (error->getErrorClass() == COLLADASaxFWL::IError::ERROR_SAXPARSER) {
COLLADASaxFWL::SaxParserError *saxParserError = (COLLADASaxFWL::SaxParserError *) error;
@@ -58,14 +61,14 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
// Workaround to avoid wrong error
if (parserError.getErrorType() == GeneratedSaxParser::ParserError::ERROR_VALIDATION_MIN_OCCURS_UNMATCHED) {
if (STREQ(parserError.getElement(), "effect")) {
- isError = false;
+ isWarning = true;
}
}
if (parserError.getErrorType() == GeneratedSaxParser::ParserError::ERROR_VALIDATION_SEQUENCE_PREVIOUS_SIBLING_NOT_PRESENT) {
if (!(STREQ(parserError.getElement(), "extra") &&
STREQ(parserError.getAdditionalText().c_str(), "sibling: fx_profile_abstract")))
{
- isError = false;
+ isWarning = true;
}
}
@@ -81,14 +84,12 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
* Accept non critical errors as warnings (i.e. texture not found)
* This makes the importer more graceful, so it now imports what makes sense.
*/
- isError = (saxFWLError->getSeverity() != COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL);
+ isWarning = (saxFWLError->getSeverity() == COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL);
std::cout << "Sax FWL Error: " << saxFWLError->getErrorMessage() << std::endl;
}
else {
std::cout << "opencollada error: " << error->getFullErrorMessage() << std::endl;
}
- mError |= isError;
-
- return isError; // let OpenCollada decide when to abort
+ return isWarning;
}
diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h
index 33a7527f383..b6a7c1f1b4e 100644
--- a/source/blender/collada/ExportSettings.h
+++ b/source/blender/collada/ExportSettings.h
@@ -27,11 +27,24 @@
#ifndef __EXPORTSETTINGS_H__
#define __EXPORTSETTINGS_H__
-#include "collada.h"
-#include "collada.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLI_linklist.h"
+
+typedef enum BC_export_mesh_type {
+ BC_MESH_TYPE_VIEW,
+ BC_MESH_TYPE_RENDER
+} BC_export_mesh_type;
+
+typedef enum BC_export_transformation_type {
+ BC_TRANSFORMATION_TYPE_MATRIX,
+ BC_TRANSFORMATION_TYPE_TRANSROTLOC
+} BC_export_transformation_type;
-struct ExportSettings {
-public:
+
+typedef struct ExportSettings {
bool apply_modifiers;
BC_export_mesh_type export_mesh_type;
@@ -40,6 +53,8 @@ public:
bool include_armatures;
bool include_shapekeys;
bool deform_bones_only;
+ bool include_animations;
+ int sampling_rate;
bool active_uv_only;
bool include_material_textures;
@@ -57,6 +72,10 @@ public:
char *filepath;
LinkNode *export_set;
-};
+} ExportSettings;
+
+#ifdef __cplusplus
+}
+#endif
#endif
diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp
index a2ab3ce520b..3cdc013c137 100644
--- a/source/blender/collada/ImageExporter.cpp
+++ b/source/blender/collada/ImageExporter.cpp
@@ -158,8 +158,8 @@ bool ImagesExporter::hasImages(Scene *sce)
for (node = this->export_settings->export_set; node; node = node->next) {
Object *ob = (Object *)node->link;
- int a;
- for (a = 0; a < ob->totcol; a++) {
+
+ for (int a = 0; a < ob->totcol; a++) {
Material *ma = give_current_material(ob, a + 1);
// no material, but check all of the slots
diff --git a/source/blender/collada/ImportSettings.h b/source/blender/collada/ImportSettings.h
index 4a2d4e8046a..fb4277b048f 100644
--- a/source/blender/collada/ImportSettings.h
+++ b/source/blender/collada/ImportSettings.h
@@ -27,10 +27,7 @@
#ifndef __IMPORTSETTINGS_H__
#define __IMPORTSETTINGS_H__
-#include "collada.h"
-
-struct ImportSettings {
-public:
+typedef struct ImportSettings {
bool import_units;
bool find_chains;
bool auto_connect;
@@ -38,6 +35,6 @@ public:
int min_chain_length;
char *filepath;
bool keep_bind_info;
-};
+} ImportSettings;
#endif
diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp
index f8cd487c355..ec1b14a3855 100644
--- a/source/blender/collada/MeshImporter.cpp
+++ b/source/blender/collada/MeshImporter.cpp
@@ -554,7 +554,7 @@ void MeshImporter::mesh_add_edges(Mesh *mesh, int len)
{
CustomData edata;
MEdge *medge;
- int i, totedge;
+ int totedge;
if (len == 0)
return;
@@ -574,7 +574,7 @@ void MeshImporter::mesh_add_edges(Mesh *mesh, int len)
/* set default flags */
medge = &mesh->medge[mesh->totedge];
- for (i = 0; i < len; i++, medge++)
+ for (int i = 0; i < len; i++, medge++)
medge->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT;
mesh->totedge = totedge;
@@ -608,12 +608,12 @@ void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me)
unsigned int edge_count = mp->getFaceCount();
unsigned int *indices = mp->getPositionIndices().getData();
- for (int i = 0; i < edge_count; i++, med++) {
+ for (int j = 0; j < edge_count; j++, med++) {
med->bweight = 0;
med->crease = 0;
med->flag |= ME_LOOSEEDGE;
- med->v1 = indices[2 * i];
- med->v2 = indices[2 * i + 1];
+ med->v1 = indices[2 * j];
+ med->v2 = indices[2 * j + 1];
}
}
}
diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp
index c375c09d869..f24c104892d 100644
--- a/source/blender/collada/SceneExporter.cpp
+++ b/source/blender/collada/SceneExporter.cpp
@@ -39,11 +39,6 @@ SceneExporter::SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm,
{
}
-void SceneExporter::setExportTransformationType(BC_export_transformation_type transformation_type)
-{
- this->transformation_type = transformation_type;
-}
-
void SceneExporter::exportScene(const EvaluationContext *eval_ctx, Scene *sce)
{
// <library_visual_scenes> <visual_scene>
@@ -139,7 +134,7 @@ void SceneExporter::writeNodes(const EvaluationContext *eval_ctx, Object *ob, Sc
// for skinned mesh we write obmat in <bind_shape_matrix>
TransformWriter::add_node_transform_identity(colladaNode);
else {
- TransformWriter::add_node_transform_ob(colladaNode, ob, this->transformation_type);
+ TransformWriter::add_node_transform_ob(colladaNode, ob, this->export_settings->export_transformation_type);
}
// <instance_geometry>
@@ -180,11 +175,11 @@ void SceneExporter::writeNodes(const EvaluationContext *eval_ctx, Object *ob, Sc
if ((ob->transflag & OB_DUPLIGROUP) == OB_DUPLIGROUP && ob->dup_group) {
Group *group = ob->dup_group;
/* printf("group detected '%s'\n", group->id.name + 2); */
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
printf("\t%s\n", object->id.name);
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
}
diff --git a/source/blender/collada/SceneExporter.h b/source/blender/collada/SceneExporter.h
index ded48983bd9..3e3c15b836f 100644
--- a/source/blender/collada/SceneExporter.h
+++ b/source/blender/collada/SceneExporter.h
@@ -96,12 +96,9 @@ class SceneExporter: COLLADASW::LibraryVisualScenes, protected TransformWriter,
{
public:
SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings);
- void exportScene(const struct EvaluationContext *eval_ctx, Scene *sce);
- void setExportTransformationType(BC_export_transformation_type transformation_type);
+ void exportScene(const EvaluationContext *eval_ctx, Scene *sce);
private:
- BC_export_transformation_type transformation_type;
- // required for writeNodes() for bone-parented objects
friend class ArmatureExporter;
void exportHierarchy(const struct EvaluationContext *eval_ctx, Scene *sce);
void writeNodes(const struct EvaluationContext *eval_ctx, Object *ob, Scene *sce);
diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp
index 6c5fb0b33f3..64e3a4c36ce 100644
--- a/source/blender/collada/collada.cpp
+++ b/source/blender/collada/collada.cpp
@@ -32,103 +32,41 @@
#include "DocumentImporter.h"
#include "ExportSettings.h"
#include "ImportSettings.h"
+#include "collada.h"
extern "C"
{
#include "BKE_scene.h"
#include "BKE_context.h"
+#include "DEG_depsgraph.h"
/* make dummy file */
#include "BLI_fileops.h"
#include "BLI_linklist.h"
-int collada_import(bContext *C,
- const char *filepath,
- int import_units,
- int find_chains,
- int auto_connect,
- int fix_orientation,
- int min_chain_length,
- int keep_bind_info)
+int collada_import(bContext *C, ImportSettings *import_settings)
{
-
- ImportSettings import_settings;
- import_settings.filepath = (char *)filepath;
- import_settings.import_units = import_units != 0;
- import_settings.auto_connect = auto_connect != 0;
- import_settings.find_chains = find_chains != 0;
- import_settings.fix_orientation = fix_orientation != 0;
- import_settings.min_chain_length = min_chain_length;
- import_settings.keep_bind_info = keep_bind_info !=0;
-
- DocumentImporter imp(C, &import_settings);
- if (imp.import()) return 1;
-
- return 0;
+ DocumentImporter imp(C, import_settings);
+ return (imp.import())? 1:0;
}
-int collada_export(const EvaluationContext *eval_ctx,
+int collada_export(EvaluationContext *eval_ctx,
Scene *sce,
- ViewLayer *view_layer,
- const char *filepath,
-
- int apply_modifiers,
- BC_export_mesh_type export_mesh_type,
-
- int selected,
- int include_children,
- int include_armatures,
- int include_shapekeys,
- int deform_bones_only,
-
- int active_uv_only,
- int include_material_textures,
- int use_texture_copies,
-
- int triangulate,
- int use_object_instantiation,
- int use_blender_profile,
- int sort_by_name,
- BC_export_transformation_type export_transformation_type,
- int open_sim,
- int limit_precision,
- int keep_bind_info)
+ ExportSettings *export_settings)
{
- ExportSettings export_settings;
-
- export_settings.filepath = (char *)filepath;
-
- export_settings.apply_modifiers = apply_modifiers != 0;
- export_settings.export_mesh_type = export_mesh_type;
- export_settings.selected = selected != 0;
- export_settings.include_children = include_children != 0;
- export_settings.include_armatures = include_armatures != 0;
- export_settings.include_shapekeys = include_shapekeys != 0;
- export_settings.deform_bones_only = deform_bones_only != 0;
-
- export_settings.active_uv_only = active_uv_only != 0;
- export_settings.include_material_textures= include_material_textures != 0;
- export_settings.use_texture_copies = use_texture_copies != 0;
-
- export_settings.triangulate = triangulate != 0;
- export_settings.use_object_instantiation = use_object_instantiation != 0;
- export_settings.use_blender_profile = use_blender_profile != 0;
- export_settings.sort_by_name = sort_by_name != 0;
- export_settings.export_transformation_type = export_transformation_type;
- export_settings.open_sim = open_sim != 0;
- export_settings.limit_precision = limit_precision != 0;
- export_settings.keep_bind_info = keep_bind_info !=0;
+ ViewLayer *view_layer = eval_ctx->view_layer;
int includeFilter = OB_REL_NONE;
- if (export_settings.include_armatures) includeFilter |= OB_REL_MOD_ARMATURE;
- if (export_settings.include_children) includeFilter |= OB_REL_CHILDREN_RECURSIVE;
+ if (export_settings->include_armatures) includeFilter |= OB_REL_MOD_ARMATURE;
+ if (export_settings->include_children) includeFilter |= OB_REL_CHILDREN_RECURSIVE;
+
+ eObjectSet objectSet = (export_settings->selected) ? OB_SET_SELECTED : OB_SET_ALL;
+ export_settings->export_set = BKE_object_relational_superset(view_layer, objectSet, (eObRelationTypes)includeFilter);
- eObjectSet objectSet = (export_settings.selected) ? OB_SET_SELECTED : OB_SET_ALL;
- export_settings.export_set = BKE_object_relational_superset(view_layer, objectSet, (eObRelationTypes)includeFilter);
- int export_count = BLI_linklist_count(export_settings.export_set);
+ int export_count = BLI_linklist_count(export_settings->export_set);
if (export_count == 0) {
- if (export_settings.selected) {
+ if (export_settings->selected) {
fprintf(stderr, "Collada: Found no objects to export.\nPlease ensure that all objects which shall be exported are also visible in the 3D Viewport.\n");
}
else {
@@ -136,14 +74,14 @@ int collada_export(const EvaluationContext *eval_ctx,
}
}
else {
- if (export_settings.sort_by_name)
- bc_bubble_sort_by_Object_name(export_settings.export_set);
+ if (export_settings->sort_by_name)
+ bc_bubble_sort_by_Object_name(export_settings->export_set);
}
- DocumentExporter exporter(&export_settings);
- int status = exporter.exportCurrentScene(eval_ctx, sce);
+ DocumentExporter exporter(eval_ctx, export_settings);
+ int status = exporter.exportCurrentScene(sce);
- BLI_linklist_free(export_settings.export_set, NULL);
+ BLI_linklist_free(export_settings->export_set, NULL);
return (status) ? -1:export_count;
}
diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h
index eb3964f9cb7..f95fca03b65 100644
--- a/source/blender/collada/collada.h
+++ b/source/blender/collada/collada.h
@@ -28,6 +28,10 @@
#define __COLLADA_H__
#include <stdlib.h>
+
+#include "ImportSettings.h"
+#include "ExportSettings.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -36,16 +40,6 @@ extern "C" {
#include "BLI_path_util.h"
#include "RNA_types.h"
-typedef enum BC_export_mesh_type {
- BC_MESH_TYPE_VIEW,
- BC_MESH_TYPE_RENDER
-} BC_export_mesh_type;
-
-typedef enum BC_export_transformation_type {
- BC_TRANSFORMATION_TYPE_MATRIX,
- BC_TRANSFORMATION_TYPE_TRANSROTLOC
-} BC_export_transformation_type;
-
struct bContext;
struct Scene;
struct ViewLayer;
@@ -55,41 +49,12 @@ struct EvaluationContext;
* both return 1 on success, 0 on error
*/
int collada_import(struct bContext *C,
- const char *filepath,
- int import_units,
- int find_chains,
- int auto_connect,
- int fix_orientation,
- int min_chain_length,
+ ImportSettings *import_settings);
- int keep_bind_info);
-int collada_export(const struct EvaluationContext *eval_ctx,
+int collada_export(struct EvaluationContext *eval_ctx,
struct Scene *sce,
- struct ViewLayer *view_layer,
- const char *filepath,
- int apply_modifiers,
- BC_export_mesh_type export_mesh_type,
-
- int selected,
- int include_children,
- int include_armatures,
- int include_shapekeys,
- int deform_bones_only,
-
- int active_uv_only,
- int include_material_textures,
- int use_texture_copies,
-
- int triangulate,
- int use_object_instantiation,
- int use_blender_profile,
- int sort_by_name,
- BC_export_transformation_type export_transformation_type,
-
- int open_sim,
- int limit_precision,
- int keep_bind_info);
+ ExportSettings *export_settings);
#ifdef __cplusplus
}
diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp
index 6ebde6bd773..cf4dcb5eb42 100644
--- a/source/blender/collada/collada_internal.cpp
+++ b/source/blender/collada/collada_internal.cpp
@@ -327,12 +327,12 @@ std::string get_light_id(Object *ob)
return translate_id(id_name(ob)) + "-light";
}
-std::string get_joint_id(Bone *bone, Object *ob_arm)
+std::string get_joint_id(Object *ob, Bone *bone)
{
- return translate_id(id_name(ob_arm) + "_" + bone->name);
+ return translate_id(id_name(ob) + "_" + bone->name);
}
-std::string get_joint_sid(Bone *bone, Object *ob_arm)
+std::string get_joint_sid(Bone *bone)
{
return translate_id(bone->name);
}
diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h
index 1c7aa160f57..299e13326ce 100644
--- a/source/blender/collada/collada_internal.h
+++ b/source/blender/collada/collada_internal.h
@@ -97,8 +97,8 @@ extern std::string get_geometry_id(Object *ob, bool use_instantiation);
extern std::string get_light_id(Object *ob);
-extern std::string get_joint_id(Bone *bone, Object *ob_arm);
-extern std::string get_joint_sid(Bone *bone, Object *ob_arm);
+extern std::string get_joint_id(Object *ob, Bone *bone);
+extern std::string get_joint_sid(Bone *bone);
extern std::string get_camera_id(Object *ob);
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index f351ebf7952..cc18cea662a 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -32,6 +32,8 @@
#include "COLLADAFWMeshPrimitive.h"
#include "COLLADAFWMeshVertexData.h"
+#include <set>
+
extern "C" {
#include "DNA_modifier_types.h"
#include "DNA_customdata_types.h"
@@ -51,6 +53,7 @@ extern "C" {
#include "BKE_mesh.h"
#include "BKE_scene.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_main.h"
#include "ED_armature.h"
@@ -135,6 +138,30 @@ int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
return true;
}
+Scene *bc_get_scene(bContext *C)
+{
+ return CTX_data_scene(C);
+}
+
+Main *bc_get_main()
+{
+ return G.main;
+}
+
+EvaluationContext *bc_get_evaluation_context()
+{
+ Main *bmain = G.main;
+ return bmain->eval_ctx;
+}
+
+
+void bc_update_scene(EvaluationContext *eval_ctx, Scene *scene, float ctime)
+{
+ BKE_scene_frame_set(scene, ctime);
+ Main *bmain = bc_get_main();
+ BKE_scene_graph_update_for_newframe(eval_ctx, eval_ctx->depsgraph, bmain, scene, eval_ctx->view_layer);
+}
+
Object *bc_add_object(Scene *scene, ViewLayer *view_layer, int type, const char *name)
{
Object *ob = BKE_object_add_only_object(G.main, type, name);
@@ -384,6 +411,35 @@ void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], floa
}
}
+/*
+* Create rotation_quaternion from a delta rotation and a reference quat
+*
+* Input:
+* mat_from: The rotation matrix before rotation
+* mat_to : The rotation matrix after rotation
+* qref : the quat corresponding to mat_from
+*
+* Output:
+* rot : the calculated result (quaternion)
+*
+*/
+void bc_rotate_from_reference_quat(float quat_to[4], float quat_from[4], float mat_to[4][4])
+{
+ float qd[4];
+ float matd[4][4];
+ float mati[4][4];
+ float mat_from[4][4];
+ quat_to_mat4(mat_from, quat_from);
+
+ // Calculate the difference matrix matd between mat_from and mat_to
+ invert_m4_m4(mati, mat_from);
+ mul_m4_m4m4(matd, mati, mat_to);
+
+ mat4_to_quat(qd, matd);
+
+ mul_qt_qtqt(quat_to, qd, quat_from); // rot is the final rotation corresponding to mat_to
+}
+
void bc_triangulate_mesh(Mesh *me)
{
bool use_beauty = false;
@@ -841,3 +897,189 @@ void bc_sanitize_mat(float mat[4][4], int precision)
for (int j = 0; j < 4; j++)
mat[i][j] = double_round(mat[i][j], precision);
}
+
+void bc_sanitize_mat(double mat[4][4], int precision)
+{
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ mat[i][j] = double_round(mat[i][j], precision);
+}
+
+void bc_copy_m4_farray(float r[4][4], float *a)
+{
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ r[i][j] = *a++;
+}
+
+void bc_copy_farray_m4(float *r, float a[4][4])
+{
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ *r++ = a[i][j];
+
+}
+
+/*
+ * Returns name of Active UV Layer or empty String if no active UV Layer defined
+ */
+std::string bc_get_active_uvlayer_name(Mesh *me)
+{
+ int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ if (num_layers) {
+ char *layer_name = bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE);
+ if (layer_name) {
+ return std::string(layer_name);
+ }
+ }
+ return "";
+}
+
+/*
+* Returns name of Active UV Layer or empty String if no active UV Layer defined.
+* Assuming the Object is of type MESH
+*/
+std::string bc_get_active_uvlayer_name(Object *ob)
+{
+ Mesh *me = (Mesh *)ob->data;
+ return bc_get_active_uvlayer_name(me);
+}
+
+/*
+ * Returns UV Layer name or empty string if layer index is out of range
+ */
+std::string bc_get_uvlayer_name(Mesh *me, int layer)
+{
+ int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ if (num_layers && layer < num_layers) {
+ char *layer_name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, layer);
+ if (layer_name) {
+ return std::string(layer_name);
+ }
+ }
+ return "";
+}
+
+#if 0
+/**********************************************************************
+*
+* Return the list of Mesh objects with assigned UVtextures and Images
+* Note: We need to create artificaial materials for each of them
+*
+***********************************************************************/
+std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers)
+{
+ std::set <Object *> UVObjects;
+ Base *base = (Base *)sce->base.first;
+
+ while (base) {
+ Object *ob = base->object;
+ bool has_uvimage = false;
+ if (ob->type == OB_MESH) {
+ Mesh *me = (Mesh *)ob->data;
+ int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
+
+ for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
+ if (all_uv_layers || active_uv_layer == i)
+ {
+ if (me->pdata.layers[i].type == CD_MTEXPOLY) {
+ MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
+ MPoly *mpoly = me->mpoly;
+ for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
+
+ Image *ima = txface->tpage;
+ if (ima != NULL) {
+ has_uvimage = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (has_uvimage) {
+ UVObjects.insert(ob);
+ }
+ }
+ base = base->next;
+ }
+ return UVObjects;
+}
+
+/**********************************************************************
+*
+* Return the list of UV Texture images from all exported Mesh Items
+* Note: We need to create one artificial material for each Image.
+*
+***********************************************************************/
+std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers)
+{
+ std::set <Image *> UVImages;
+ Base *base = (Base *)sce->base.first;
+
+ while (base) {
+ Object *ob = base->object;
+ bool has_uvimage = false;
+ if (ob->type == OB_MESH) {
+ Mesh *me = (Mesh *)ob->data;
+ int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
+
+ for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
+ if (all_uv_layers || active_uv_layer == i)
+ {
+ if (me->pdata.layers[i].type == CD_MTEXPOLY) {
+ MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
+ MPoly *mpoly = me->mpoly;
+ for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
+
+ Image *ima = txface->tpage;
+ if (ima != NULL) {
+ if (UVImages.find(ima) == UVImages.end())
+ UVImages.insert(ima);
+ }
+ }
+ }
+ }
+ }
+ }
+ base = base->next;
+ }
+ return UVImages;
+}
+
+/**********************************************************************
+*
+* Return the list of UV Texture images for the given Object
+* Note: We need to create one artificial material for each Image.
+*
+***********************************************************************/
+std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers)
+{
+ std::set <Image *> UVImages;
+
+ bool has_uvimage = false;
+ if (ob->type == OB_MESH) {
+ Mesh *me = (Mesh *)ob->data;
+ int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
+
+ for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
+ if (all_uv_layers || active_uv_layer == i)
+ {
+ if (me->pdata.layers[i].type == CD_MTEXPOLY) {
+ MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
+ MPoly *mpoly = me->mpoly;
+ for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
+
+ Image *ima = txface->tpage;
+ if (ima != NULL) {
+ if (UVImages.find(ima) == UVImages.end())
+ UVImages.insert(ima);
+ }
+ }
+ }
+ }
+ }
+ }
+ return UVImages;
+}
+#endif
diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h
index 5d6e836b9c3..52767557397 100644
--- a/source/blender/collada/collada_utils.h
+++ b/source/blender/collada/collada_utils.h
@@ -64,6 +64,11 @@ struct EvaluationContext;
typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex *> > TexIndexTextureArrayMap;
+extern Scene *bc_get_scene(bContext *C);
+extern Main *bc_get_main();
+extern EvaluationContext *bc_get_evaluation_context();
+extern void bc_update_scene(EvaluationContext *eval_ctx, Scene *scene, float ctime);
+
extern float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index);
extern int bc_test_parent_loop(Object *par, Object *ob);
extern int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space = true);
@@ -93,13 +98,22 @@ extern void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_sce
extern void bc_match_scale(std::vector<Object *> *objects_done, UnitConverter &unit_converter, bool scale_to_scene);
extern void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size);
+extern void bc_rotate_from_reference_quat(float quat_to[4], float quat_from[4], float mat_to[4][4]);
extern void bc_triangulate_mesh(Mesh *me);
extern bool bc_is_leaf_bone(Bone *bone);
extern EditBone *bc_get_edit_bone(bArmature * armature, char *name);
extern int bc_set_layer(int bitfield, int layer, bool enable);
extern int bc_set_layer(int bitfield, int layer);
+
+inline bool bc_in_range(float a, float b, float range) {
+ return fabsf(a - b) < range;
+}
+void bc_copy_m4_farray(float r[4][4], float *a);
+void bc_copy_farray_m4(float *r, float a[4][4]);
+
extern void bc_sanitize_mat(float mat[4][4], int precision);
+extern void bc_sanitize_mat(double mat[4][4], int precision);
extern IDProperty *bc_get_IDProperty(Bone *bone, std::string key);
extern void bc_set_IDProperty(EditBone *ebone, const char *key, float value);
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index 3e1dd83112a..a141495e5ae 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -31,6 +31,7 @@ set(INC
../blenkernel
../blenlib
../blentranslation
+ ../depsgraph
../imbuf
../makesdna
../makesrna
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp
index 68f934008a4..e2dc289eb1c 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.cpp
+++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp
@@ -131,18 +131,18 @@ void WorkScheduler::start(CompositorContext &context)
#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
unsigned int index;
g_cpuqueue = BLI_thread_queue_init();
- BLI_init_threads(&g_cputhreads, thread_execute_cpu, g_cpudevices.size());
+ BLI_threadpool_init(&g_cputhreads, thread_execute_cpu, g_cpudevices.size());
for (index = 0; index < g_cpudevices.size(); index++) {
Device *device = g_cpudevices[index];
- BLI_insert_thread(&g_cputhreads, device);
+ BLI_threadpool_insert(&g_cputhreads, device);
}
#ifdef COM_OPENCL_ENABLED
if (context.getHasActiveOpenCLDevices()) {
g_gpuqueue = BLI_thread_queue_init();
- BLI_init_threads(&g_gputhreads, thread_execute_gpu, g_gpudevices.size());
+ BLI_threadpool_init(&g_gputhreads, thread_execute_gpu, g_gpudevices.size());
for (index = 0; index < g_gpudevices.size(); index++) {
Device *device = g_gpudevices[index];
- BLI_insert_thread(&g_gputhreads, device);
+ BLI_threadpool_insert(&g_gputhreads, device);
}
g_openclActive = true;
}
@@ -172,13 +172,13 @@ void WorkScheduler::stop()
{
#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
BLI_thread_queue_nowait(g_cpuqueue);
- BLI_end_threads(&g_cputhreads);
+ BLI_threadpool_end(&g_cputhreads);
BLI_thread_queue_free(g_cpuqueue);
g_cpuqueue = NULL;
#ifdef COM_OPENCL_ENABLED
if (g_openclActive) {
BLI_thread_queue_nowait(g_gpuqueue);
- BLI_end_threads(&g_gputhreads);
+ BLI_threadpool_end(&g_gputhreads);
BLI_thread_queue_free(g_gpuqueue);
g_gpuqueue = NULL;
}
diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp
index 81891d853d2..1399749fc8d 100644
--- a/source/blender/compositor/nodes/COM_ImageNode.cpp
+++ b/source/blender/compositor/nodes/COM_ImageNode.cpp
@@ -105,7 +105,7 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
}
/* returns the image view to use for the current active view */
- if (BLI_listbase_count_ex(&image->rr->views, 2) > 1) {
+ if (BLI_listbase_count_at_most(&image->rr->views, 2) > 1) {
const int view_image = imageuser->view;
const bool is_allview = (view_image == 0); /* if view selected == All (0) */
diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp
index 15ffff2fc90..fe13f3d60a2 100644
--- a/source/blender/compositor/operations/COM_CompositorOperation.cpp
+++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp
@@ -108,9 +108,9 @@ void CompositorOperation::deinitExecution()
re = NULL;
}
- BLI_lock_thread(LOCK_DRAW_IMAGE);
+ BLI_thread_lock(LOCK_DRAW_IMAGE);
BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE);
- BLI_unlock_thread(LOCK_DRAW_IMAGE);
+ BLI_thread_unlock(LOCK_DRAW_IMAGE);
}
else {
if (this->m_outputBuffer) {
diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.h b/source/blender/compositor/operations/COM_KeyingScreenOperation.h
index b1a5c0c39c7..45195b1e98d 100644
--- a/source/blender/compositor/operations/COM_KeyingScreenOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.h
@@ -35,7 +35,7 @@
#include "BLI_string.h"
extern "C" {
-# include "BLI_voronoi.h"
+# include "BLI_voronoi_2d.h"
}
/**
diff --git a/source/blender/compositor/operations/COM_MapRangeOperation.cpp b/source/blender/compositor/operations/COM_MapRangeOperation.cpp
index 7a89ba91b4c..7a38d066122 100644
--- a/source/blender/compositor/operations/COM_MapRangeOperation.cpp
+++ b/source/blender/compositor/operations/COM_MapRangeOperation.cpp
@@ -65,6 +65,11 @@ void MapRangeOperation::executePixelSampled(float output[4], float x, float y, P
dest_min = inputs[3];
dest_max = inputs[4];
+ if (fabsf(source_max - source_min) < 1e-6f) {
+ output[0] = 0.0f;
+ return;
+ }
+
if (value >= -BLENDER_ZMAX && value <= BLENDER_ZMAX) {
value = (value - source_min) / (source_max - source_min);
value = dest_min + value * (dest_max - dest_min);
diff --git a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp
index 1145abd076a..75a85ad7e33 100644
--- a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp
+++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp
@@ -28,7 +28,7 @@ extern "C" {
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_math_color.h"
-#include "BLI_jitter.h"
+#include "BLI_jitter_2d.h"
#include "BKE_movieclip.h"
#include "BKE_node.h"
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h
index 1be15906770..7cfead7e98c 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.h
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.h
@@ -30,8 +30,6 @@
#include "BKE_image.h"
extern "C" {
# include "RE_pipeline.h"
-# include "RE_shader_ext.h"
-# include "RE_render_ext.h"
# include "MEM_guardedalloc.h"
}
@@ -46,7 +44,7 @@ protected:
* Reference to the scene object.
*/
Scene *m_scene;
-
+
/**
* layerId of the layer where this operation needs to get its data from
*/
@@ -61,24 +59,24 @@ protected:
* cached instance to the float buffer inside the layer
*/
float *m_inputBuffer;
-
+
/**
* renderpass where this operation needs to get its data from
*/
std::string m_passName;
-
+
int m_elementsize;
/**
* @brief render data used for active rendering
*/
const RenderData *m_rd;
-
+
/**
* Determine the output resolution. The resolution is retrieved from the Renderer
*/
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
-
+
/**
* retrieve the reference to the float buffer of the renderer.
*/
diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp
index 36f06e92436..bccfe025089 100644
--- a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp
@@ -20,16 +20,30 @@
* Monique Dewanchand
*/
-#include "COM_VectorBlurOperation.h"
-#include "BLI_math.h"
-
+#include <string.h>
#include "MEM_guardedalloc.h"
-
-// use the implementation of blender internal renderer to calculate the vector blur.
+#include "BLI_math.h"
extern "C" {
-# include "RE_pipeline.h"
+ #include "BLI_jitter_2d.h"
}
+#include "COM_VectorBlurOperation.h"
+
+/* Defined */
+#define PASS_VECTOR_MAX 10000.0f
+
+/* Forward declarations */
+struct ZSpan;
+struct DrawBufPixel;
+void zbuf_accumulate_vecblur(
+ NodeBlurData *nbd, int xsize, int ysize, float *newrect,
+ const float *imgrect, float *vecbufrect, const float *zbufrect);
+void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty, float clipcrop);
+void zbuf_free_span(ZSpan *zspan);
+void antialias_tagbuf(int xsize, int ysize, char *rectmove);
+
+
+/* VectorBlurOperation */
VectorBlurOperation::VectorBlurOperation() : NodeOperation()
{
this->addInputSocket(COM_DT_COLOR);
@@ -51,7 +65,7 @@ void VectorBlurOperation::initExecution()
this->m_inputSpeedProgram = getInputSocketReader(2);
this->m_cachedInstance = NULL;
QualityStepHelper::initExecution(COM_QH_INCREASE);
-
+
}
void VectorBlurOperation::executePixel(float output[4], int x, int y, void *data)
@@ -77,7 +91,7 @@ void *VectorBlurOperation::initializeTileData(rcti *rect)
if (this->m_cachedInstance) {
return this->m_cachedInstance;
}
-
+
lockMutex();
if (this->m_cachedInstance == NULL) {
MemoryBuffer *tile = (MemoryBuffer *)this->m_inputImageProgram->initializeTileData(rect);
@@ -114,6 +128,690 @@ void VectorBlurOperation::generateVectorBlur(float *data, MemoryBuffer *inputIma
blurdata.minspeed = this->m_settings->minspeed;
blurdata.curved = this->m_settings->curved;
blurdata.fac = this->m_settings->fac;
- RE_zbuf_accumulate_vecblur(&blurdata, this->getWidth(), this->getHeight(), data, inputImage->getBuffer(), inputSpeed->getBuffer(), inputZ->getBuffer());
+ zbuf_accumulate_vecblur(&blurdata, this->getWidth(), this->getHeight(), data, inputImage->getBuffer(), inputSpeed->getBuffer(), inputZ->getBuffer());
return;
}
+
+/* ****************** Spans ******************************* */
+/* span fill in method, is also used to localize data for zbuffering */
+typedef struct ZSpan {
+ /* range for clipping */
+ int rectx, recty;
+
+ /* actual filled in range */
+ int miny1, maxy1, miny2, maxy2;
+ /* vertex pointers detect min/max range in */
+ const float *minp1, *maxp1, *minp2, *maxp2;
+ float *span1, *span2;
+
+ /* transform from hoco to zbuf co */
+ float zmulx, zmuly, zofsx, zofsy;
+
+ int *rectz;
+ DrawBufPixel* rectdraw;
+ float clipcrop;
+
+} ZSpan;
+
+/* each zbuffer has coordinates transformed to local rect coordinates, so we can simply clip */
+void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty, float clipcrop)
+{
+ memset(zspan, 0, sizeof(ZSpan));
+
+ zspan->rectx= rectx;
+ zspan->recty= recty;
+
+ zspan->span1= (float*)MEM_mallocN(recty*sizeof(float), "zspan");
+ zspan->span2= (float*)MEM_mallocN(recty*sizeof(float), "zspan");
+
+ zspan->clipcrop= clipcrop;
+}
+
+void zbuf_free_span(ZSpan *zspan)
+{
+ if (zspan) {
+ if (zspan->span1) MEM_freeN(zspan->span1);
+ if (zspan->span2) MEM_freeN(zspan->span2);
+ zspan->span1= zspan->span2= NULL;
+ }
+}
+
+/* reset range for clipping */
+static void zbuf_init_span(ZSpan *zspan)
+{
+ zspan->miny1= zspan->miny2= zspan->recty+1;
+ zspan->maxy1= zspan->maxy2= -1;
+ zspan->minp1= zspan->maxp1= zspan->minp2= zspan->maxp2= NULL;
+}
+
+static void zbuf_add_to_span(ZSpan *zspan, const float v1[2], const float v2[2])
+{
+ const float *minv, *maxv;
+ float *span;
+ float xx1, dx0, xs0;
+ int y, my0, my2;
+
+ if (v1[1]<v2[1]) {
+ minv= v1; maxv= v2;
+ }
+ else {
+ minv= v2; maxv= v1;
+ }
+
+ my0= ceil(minv[1]);
+ my2= floor(maxv[1]);
+
+ if (my2<0 || my0>= zspan->recty) return;
+
+ /* clip top */
+ if (my2>=zspan->recty) my2= zspan->recty-1;
+ /* clip bottom */
+ if (my0<0) my0= 0;
+
+ if (my0>my2) return;
+ /* if (my0>my2) should still fill in, that way we get spans that skip nicely */
+
+ xx1= maxv[1]-minv[1];
+ if (xx1>FLT_EPSILON) {
+ dx0= (minv[0]-maxv[0])/xx1;
+ xs0= dx0*(minv[1]-my2) + minv[0];
+ }
+ else {
+ dx0 = 0.0f;
+ xs0 = min_ff(minv[0], maxv[0]);
+ }
+
+ /* empty span */
+ if (zspan->maxp1 == NULL) {
+ span= zspan->span1;
+ }
+ else { /* does it complete left span? */
+ if ( maxv == zspan->minp1 || minv==zspan->maxp1) {
+ span= zspan->span1;
+ }
+ else {
+ span= zspan->span2;
+ }
+ }
+
+ if (span==zspan->span1) {
+// printf("left span my0 %d my2 %d\n", my0, my2);
+ if (zspan->minp1==NULL || zspan->minp1[1] > minv[1] ) {
+ zspan->minp1= minv;
+ }
+ if (zspan->maxp1==NULL || zspan->maxp1[1] < maxv[1] ) {
+ zspan->maxp1= maxv;
+ }
+ if (my0<zspan->miny1) zspan->miny1= my0;
+ if (my2>zspan->maxy1) zspan->maxy1= my2;
+ }
+ else {
+// printf("right span my0 %d my2 %d\n", my0, my2);
+ if (zspan->minp2==NULL || zspan->minp2[1] > minv[1] ) {
+ zspan->minp2= minv;
+ }
+ if (zspan->maxp2==NULL || zspan->maxp2[1] < maxv[1] ) {
+ zspan->maxp2= maxv;
+ }
+ if (my0<zspan->miny2) zspan->miny2= my0;
+ if (my2>zspan->maxy2) zspan->maxy2= my2;
+ }
+
+ for (y=my2; y>=my0; y--, xs0+= dx0) {
+ /* xs0 is the xcoord! */
+ span[y]= xs0;
+ }
+}
+
+/* ******************** VECBLUR ACCUM BUF ************************* */
+
+typedef struct DrawBufPixel {
+ const float *colpoin;
+ float alpha;
+} DrawBufPixel;
+
+
+static void zbuf_fill_in_rgba(ZSpan *zspan, DrawBufPixel *col, float *v1, float *v2, float *v3, float *v4)
+{
+ DrawBufPixel *rectpofs, *rp;
+ double zxd, zyd, zy0, zverg;
+ float x0, y0, z0;
+ float x1, y1, z1, x2, y2, z2, xx1;
+ const float *span1, *span2;
+ float *rectzofs, *rz;
+ int x, y;
+ int sn1, sn2, rectx, my0, my2;
+
+ /* init */
+ zbuf_init_span(zspan);
+
+ /* set spans */
+ zbuf_add_to_span(zspan, v1, v2);
+ zbuf_add_to_span(zspan, v2, v3);
+ zbuf_add_to_span(zspan, v3, v4);
+ zbuf_add_to_span(zspan, v4, v1);
+
+ /* clipped */
+ if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
+
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
+
+ // printf("my %d %d\n", my0, my2);
+ if (my2<my0) return;
+
+ /* ZBUF DX DY, in floats still */
+ x1= v1[0]- v2[0];
+ x2= v2[0]- v3[0];
+ y1= v1[1]- v2[1];
+ y2= v2[1]- v3[1];
+ z1= v1[2]- v2[2];
+ z2= v2[2]- v3[2];
+ x0= y1*z2-z1*y2;
+ y0= z1*x2-x1*z2;
+ z0= x1*y2-y1*x2;
+
+ if (z0==0.0f) return;
+
+ xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
+
+ zxd= -(double)x0/(double)z0;
+ zyd= -(double)y0/(double)z0;
+ zy0= ((double)my2)*zyd + (double)xx1;
+
+ /* start-offset in rect */
+ rectx= zspan->rectx;
+ rectzofs= (float *)(zspan->rectz + rectx*my2);
+ rectpofs= ((DrawBufPixel *)zspan->rectdraw) + rectx*my2;
+
+ /* correct span */
+ sn1= (my0 + my2)/2;
+ if (zspan->span1[sn1] < zspan->span2[sn1]) {
+ span1= zspan->span1+my2;
+ span2= zspan->span2+my2;
+ }
+ else {
+ span1= zspan->span2+my2;
+ span2= zspan->span1+my2;
+ }
+
+ for (y=my2; y>=my0; y--, span1--, span2--) {
+
+ sn1= floor(*span1);
+ sn2= floor(*span2);
+ sn1++;
+
+ if (sn2>=rectx) sn2= rectx-1;
+ if (sn1<0) sn1= 0;
+
+ if (sn2>=sn1) {
+ zverg= (double)sn1*zxd + zy0;
+ rz= rectzofs+sn1;
+ rp= rectpofs+sn1;
+ x= sn2-sn1;
+
+ while (x>=0) {
+ if (zverg < (double)*rz) {
+ *rz= zverg;
+ *rp= *col;
+ }
+ zverg+= zxd;
+ rz++;
+ rp++;
+ x--;
+ }
+ }
+
+ zy0-=zyd;
+ rectzofs-= rectx;
+ rectpofs-= rectx;
+ }
+}
+
+/* char value==255 is filled in, rest should be zero */
+/* returns alpha values, but sets alpha to 1 for zero alpha pixels that have an alpha value as neighbor */
+void antialias_tagbuf(int xsize, int ysize, char *rectmove)
+{
+ char *row1, *row2, *row3;
+ char prev, next;
+ int a, x, y, step;
+
+ /* 1: tag pixels to be candidate for AA */
+ for (y=2; y<ysize; y++) {
+ /* setup rows */
+ row1= rectmove + (y-2)*xsize;
+ row2= row1 + xsize;
+ row3= row2 + xsize;
+ for (x=2; x<xsize; x++, row1++, row2++, row3++) {
+ if (row2[1]) {
+ if (row2[0]==0 || row2[2]==0 || row1[1]==0 || row3[1]==0)
+ row2[1]= 128;
+ }
+ }
+ }
+
+ /* 2: evaluate horizontal scanlines and calculate alphas */
+ row1= rectmove;
+ for (y=0; y<ysize; y++) {
+ row1++;
+ for (x=1; x<xsize; x++, row1++) {
+ if (row1[0]==128 && row1[1]==128) {
+ /* find previous color and next color and amount of steps to blend */
+ prev= row1[-1];
+ step= 1;
+ while (x+step<xsize && row1[step]==128)
+ step++;
+
+ if (x+step!=xsize) {
+ /* now we can blend values */
+ next= row1[step];
+
+ /* note, prev value can be next value, but we do this loop to clear 128 then */
+ for (a=0; a<step; a++) {
+ int fac, mfac;
+
+ fac= ((a+1)<<8)/(step+1);
+ mfac= 255-fac;
+
+ row1[a]= (prev*mfac + next*fac)>>8;
+ }
+ }
+ }
+ }
+ }
+
+ /* 3: evaluate vertical scanlines and calculate alphas */
+ /* use for reading a copy of the original tagged buffer */
+ for (x=0; x<xsize; x++) {
+ row1= rectmove + x+xsize;
+
+ for (y=1; y<ysize; y++, row1+=xsize) {
+ if (row1[0]==128 && row1[xsize]==128) {
+ /* find previous color and next color and amount of steps to blend */
+ prev= row1[-xsize];
+ step= 1;
+ while (y+step<ysize && row1[step*xsize]==128)
+ step++;
+
+ if (y+step!=ysize) {
+ /* now we can blend values */
+ next= row1[step*xsize];
+ /* note, prev value can be next value, but we do this loop to clear 128 then */
+ for (a=0; a<step; a++) {
+ int fac, mfac;
+
+ fac= ((a+1)<<8)/(step+1);
+ mfac= 255-fac;
+
+ row1[a*xsize]= (prev*mfac + next*fac)>>8;
+ }
+ }
+ }
+ }
+ }
+
+ /* last: pixels with 0 we fill in zbuffer, with 1 we skip for mask */
+ for (y=2; y<ysize; y++) {
+ /* setup rows */
+ row1= rectmove + (y-2)*xsize;
+ row2= row1 + xsize;
+ row3= row2 + xsize;
+ for (x=2; x<xsize; x++, row1++, row2++, row3++) {
+ if (row2[1]==0) {
+ if (row2[0]>1 || row2[2]>1 || row1[1]>1 || row3[1]>1)
+ row2[1]= 1;
+ }
+ }
+ }
+}
+
+/* in: two vectors, first vector points from origin back in time, 2nd vector points to future */
+/* we make this into 3 points, center point is (0, 0) */
+/* and offset the center point just enough to make curve go through midpoint */
+
+static void quad_bezier_2d(float *result, float *v1, float *v2, float *ipodata)
+{
+ float p1[2], p2[2], p3[2];
+
+ p3[0]= -v2[0];
+ p3[1]= -v2[1];
+
+ p1[0]= v1[0];
+ p1[1]= v1[1];
+
+ /* official formula 2*p2 - 0.5*p1 - 0.5*p3 */
+ p2[0]= -0.5f*p1[0] - 0.5f*p3[0];
+ p2[1]= -0.5f*p1[1] - 0.5f*p3[1];
+
+ result[0]= ipodata[0]*p1[0] + ipodata[1]*p2[0] + ipodata[2]*p3[0];
+ result[1]= ipodata[0]*p1[1] + ipodata[1]*p2[1] + ipodata[2]*p3[1];
+}
+
+static void set_quad_bezier_ipo(float fac, float *data)
+{
+ float mfac= (1.0f-fac);
+
+ data[0]= mfac*mfac;
+ data[1]= 2.0f*mfac*fac;
+ data[2]= fac*fac;
+}
+
+void zbuf_accumulate_vecblur(
+ NodeBlurData *nbd, int xsize, int ysize, float *newrect,
+ const float *imgrect, float *vecbufrect, const float *zbufrect)
+{
+ ZSpan zspan;
+ DrawBufPixel *rectdraw, *dr;
+ static float jit[256][2];
+ float v1[3], v2[3], v3[3], v4[3], fx, fy;
+ const float *dimg, *dz, *ro;
+ float *rectvz, *dvz, *dvec1, *dvec2, *dz1, *dz2, *rectz;
+ float *minvecbufrect= NULL, *rectweight, *rw, *rectmax, *rm;
+ float maxspeedsq= (float)nbd->maxspeed*nbd->maxspeed;
+ int y, x, step, maxspeed=nbd->maxspeed, samples= nbd->samples;
+ int tsktsk= 0;
+ static int firsttime= 1;
+ char *rectmove, *dm;
+
+ zbuf_alloc_span(&zspan, xsize, ysize, 1.0f);
+ zspan.zmulx= ((float)xsize)/2.0f;
+ zspan.zmuly= ((float)ysize)/2.0f;
+ zspan.zofsx= 0.0f;
+ zspan.zofsy= 0.0f;
+
+ /* the buffers */
+ rectz= (float*)MEM_mapallocN(sizeof(float)*xsize*ysize, "zbuf accum");
+ zspan.rectz= (int *)rectz;
+
+ rectmove= (char*)MEM_mapallocN(xsize*ysize, "rectmove");
+ rectdraw= (DrawBufPixel*)MEM_mapallocN(sizeof(DrawBufPixel)*xsize*ysize, "rect draw");
+ zspan.rectdraw= rectdraw;
+
+ rectweight= (float*)MEM_mapallocN(sizeof(float)*xsize*ysize, "rect weight");
+ rectmax= (float*)MEM_mapallocN(sizeof(float)*xsize*ysize, "rect max");
+
+ /* debug... check if PASS_VECTOR_MAX still is in buffers */
+ dvec1= vecbufrect;
+ for (x= 4*xsize*ysize; x>0; x--, dvec1++) {
+ if (dvec1[0]==PASS_VECTOR_MAX) {
+ dvec1[0]= 0.0f;
+ tsktsk= 1;
+ }
+ }
+ if (tsktsk) printf("Found uninitialized speed in vector buffer... fixed.\n");
+
+ /* min speed? then copy speedbuffer to recalculate speed vectors */
+ if (nbd->minspeed) {
+ float minspeed= (float)nbd->minspeed;
+ float minspeedsq= minspeed*minspeed;
+
+ minvecbufrect= (float*)MEM_mapallocN(4*sizeof(float)*xsize*ysize, "minspeed buf");
+
+ dvec1= vecbufrect;
+ dvec2= minvecbufrect;
+ for (x= 2*xsize*ysize; x>0; x--, dvec1+=2, dvec2+=2) {
+ if (dvec1[0]==0.0f && dvec1[1]==0.0f) {
+ dvec2[0]= dvec1[0];
+ dvec2[1]= dvec1[1];
+ }
+ else {
+ float speedsq= dvec1[0]*dvec1[0] + dvec1[1]*dvec1[1];
+ if (speedsq <= minspeedsq) {
+ dvec2[0]= 0.0f;
+ dvec2[1]= 0.0f;
+ }
+ else {
+ speedsq = 1.0f - minspeed / sqrtf(speedsq);
+ dvec2[0]= speedsq*dvec1[0];
+ dvec2[1]= speedsq*dvec1[1];
+ }
+ }
+ }
+ SWAP(float *, minvecbufrect, vecbufrect);
+ }
+
+ /* make vertex buffer with averaged speed and zvalues */
+ rectvz= (float*)MEM_mapallocN(4*sizeof(float)*(xsize+1)*(ysize+1), "vertices");
+ dvz= rectvz;
+ for (y=0; y<=ysize; y++) {
+
+ if (y==0)
+ dvec1= vecbufrect + 4*y*xsize;
+ else
+ dvec1= vecbufrect + 4*(y-1)*xsize;
+
+ if (y==ysize)
+ dvec2= vecbufrect + 4*(y-1)*xsize;
+ else
+ dvec2= vecbufrect + 4*y*xsize;
+
+ for (x=0; x<=xsize; x++) {
+
+ /* two vectors, so a step loop */
+ for (step=0; step<2; step++, dvec1+=2, dvec2+=2, dvz+=2) {
+ /* average on minimal speed */
+ int div= 0;
+
+ if (x!=0) {
+ if (dvec1[-4]!=0.0f || dvec1[-3]!=0.0f) {
+ dvz[0]= dvec1[-4];
+ dvz[1]= dvec1[-3];
+ div++;
+ }
+ if (dvec2[-4]!=0.0f || dvec2[-3]!=0.0f) {
+ if (div==0) {
+ dvz[0]= dvec2[-4];
+ dvz[1]= dvec2[-3];
+ div++;
+ }
+ else if ( (ABS(dvec2[-4]) + ABS(dvec2[-3]))< (ABS(dvz[0]) + ABS(dvz[1])) ) {
+ dvz[0]= dvec2[-4];
+ dvz[1]= dvec2[-3];
+ }
+ }
+ }
+
+ if (x!=xsize) {
+ if (dvec1[0]!=0.0f || dvec1[1]!=0.0f) {
+ if (div==0) {
+ dvz[0]= dvec1[0];
+ dvz[1]= dvec1[1];
+ div++;
+ }
+ else if ( (ABS(dvec1[0]) + ABS(dvec1[1]))< (ABS(dvz[0]) + ABS(dvz[1])) ) {
+ dvz[0]= dvec1[0];
+ dvz[1]= dvec1[1];
+ }
+ }
+ if (dvec2[0]!=0.0f || dvec2[1]!=0.0f) {
+ if (div==0) {
+ dvz[0]= dvec2[0];
+ dvz[1]= dvec2[1];
+ }
+ else if ( (ABS(dvec2[0]) + ABS(dvec2[1]))< (ABS(dvz[0]) + ABS(dvz[1])) ) {
+ dvz[0]= dvec2[0];
+ dvz[1]= dvec2[1];
+ }
+ }
+ }
+ if (maxspeed) {
+ float speedsq= dvz[0]*dvz[0] + dvz[1]*dvz[1];
+ if (speedsq > maxspeedsq) {
+ speedsq = (float)maxspeed / sqrtf(speedsq);
+ dvz[0]*= speedsq;
+ dvz[1]*= speedsq;
+ }
+ }
+ }
+ }
+ }
+
+ /* set border speeds to keep border speeds on border */
+ dz1= rectvz;
+ dz2= rectvz+4*(ysize)*(xsize+1);
+ for (x=0; x<=xsize; x++, dz1+=4, dz2+=4) {
+ dz1[1]= 0.0f;
+ dz2[1]= 0.0f;
+ dz1[3]= 0.0f;
+ dz2[3]= 0.0f;
+ }
+ dz1= rectvz;
+ dz2= rectvz+4*(xsize);
+ for (y=0; y<=ysize; y++, dz1+=4*(xsize+1), dz2+=4*(xsize+1)) {
+ dz1[0]= 0.0f;
+ dz2[0]= 0.0f;
+ dz1[2]= 0.0f;
+ dz2[2]= 0.0f;
+ }
+
+ /* tag moving pixels, only these faces we draw */
+ dm= rectmove;
+ dvec1= vecbufrect;
+ for (x=xsize*ysize; x>0; x--, dm++, dvec1+=4) {
+ if ((dvec1[0]!=0.0f || dvec1[1]!=0.0f || dvec1[2]!=0.0f || dvec1[3]!=0.0f))
+ *dm= 255;
+ }
+
+ antialias_tagbuf(xsize, ysize, rectmove);
+
+ /* has to become static, the init-jit calls a random-seed, screwing up texture noise node */
+ if (firsttime) {
+ firsttime= 0;
+ BLI_jitter_init(jit, 256);
+ }
+
+ memset(newrect, 0, sizeof(float)*xsize*ysize*4);
+
+ /* accumulate */
+ samples/= 2;
+ for (step= 1; step<=samples; step++) {
+ float speedfac= 0.5f*nbd->fac*(float)step/(float)(samples+1);
+ int side;
+
+ for (side=0; side<2; side++) {
+ float blendfac, ipodata[4];
+
+ /* clear zbuf, if we draw future we fill in not moving pixels */
+ if (0)
+ for (x= xsize*ysize-1; x>=0; x--) rectz[x]= 10e16;
+ else
+ for (x= xsize*ysize-1; x>=0; x--) {
+ if (rectmove[x]==0)
+ rectz[x]= zbufrect[x];
+ else
+ rectz[x]= 10e16;
+ }
+
+ /* clear drawing buffer */
+ for (x= xsize*ysize-1; x>=0; x--) rectdraw[x].colpoin= NULL;
+
+ dimg= imgrect;
+ dm= rectmove;
+ dz= zbufrect;
+ dz1= rectvz;
+ dz2= rectvz + 4*(xsize + 1);
+
+ if (side) {
+ if (nbd->curved==0) {
+ dz1+= 2;
+ dz2+= 2;
+ }
+ speedfac= -speedfac;
+ }
+
+ set_quad_bezier_ipo(0.5f + 0.5f*speedfac, ipodata);
+
+ for (fy= -0.5f+jit[step & 255][0], y=0; y<ysize; y++, fy+=1.0f) {
+ for (fx= -0.5f+jit[step & 255][1], x=0; x<xsize; x++, fx+=1.0f, dimg+=4, dz1+=4, dz2+=4, dm++, dz++) {
+ if (*dm>1) {
+ float jfx = fx + 0.5f;
+ float jfy = fy + 0.5f;
+ DrawBufPixel col;
+
+ /* make vertices */
+ if (nbd->curved) { /* curved */
+ quad_bezier_2d(v1, dz1, dz1+2, ipodata);
+ v1[0]+= jfx; v1[1]+= jfy; v1[2]= *dz;
+
+ quad_bezier_2d(v2, dz1+4, dz1+4+2, ipodata);
+ v2[0]+= jfx+1.0f; v2[1]+= jfy; v2[2]= *dz;
+
+ quad_bezier_2d(v3, dz2+4, dz2+4+2, ipodata);
+ v3[0]+= jfx+1.0f; v3[1]+= jfy+1.0f; v3[2]= *dz;
+
+ quad_bezier_2d(v4, dz2, dz2+2, ipodata);
+ v4[0]+= jfx; v4[1]+= jfy+1.0f; v4[2]= *dz;
+ }
+ else {
+ v1[0]= speedfac*dz1[0]+jfx; v1[1]= speedfac*dz1[1]+jfy; v1[2]= *dz;
+ v2[0]= speedfac*dz1[4]+jfx+1.0f; v2[1]= speedfac*dz1[5]+jfy; v2[2]= *dz;
+ v3[0]= speedfac*dz2[4]+jfx+1.0f; v3[1]= speedfac*dz2[5]+jfy+1.0f; v3[2]= *dz;
+ v4[0]= speedfac*dz2[0]+jfx; v4[1]= speedfac*dz2[1]+jfy+1.0f; v4[2]= *dz;
+ }
+ if (*dm==255) col.alpha= 1.0f;
+ else if (*dm<2) col.alpha= 0.0f;
+ else col.alpha= ((float)*dm)/255.0f;
+ col.colpoin= dimg;
+
+ zbuf_fill_in_rgba(&zspan, &col, v1, v2, v3, v4);
+ }
+ }
+ dz1+=4;
+ dz2+=4;
+ }
+
+ /* blend with a falloff. this fixes the ugly effect you get with
+ * a fast moving object. then it looks like a solid object overlayed
+ * over a very transparent moving version of itself. in reality, the
+ * whole object should become transparent if it is moving fast, be
+ * we don't know what is behind it so we don't do that. this hack
+ * overestimates the contribution of foreground pixels but looks a
+ * bit better without a sudden cutoff. */
+ blendfac= ((samples - step)/(float)samples);
+ /* smoothstep to make it look a bit nicer as well */
+ blendfac= 3.0f*pow(blendfac, 2.0f) - 2.0f*pow(blendfac, 3.0f);
+
+ /* accum */
+ rw= rectweight;
+ rm= rectmax;
+ for (dr= rectdraw, dz2=newrect, x= xsize*ysize-1; x>=0; x--, dr++, dz2+=4, rw++, rm++) {
+ if (dr->colpoin) {
+ float bfac= dr->alpha*blendfac;
+
+ dz2[0] += bfac*dr->colpoin[0];
+ dz2[1] += bfac*dr->colpoin[1];
+ dz2[2] += bfac*dr->colpoin[2];
+ dz2[3] += bfac*dr->colpoin[3];
+
+ *rw += bfac;
+ *rm= MAX2(*rm, bfac);
+ }
+ }
+ }
+ }
+
+ /* blend between original images and accumulated image */
+ rw= rectweight;
+ rm= rectmax;
+ ro= imgrect;
+ dm= rectmove;
+ for (dz2=newrect, x= xsize*ysize-1; x>=0; x--, dz2+=4, ro+=4, rw++, rm++, dm++) {
+ float mfac = *rm;
+ float fac = (*rw == 0.0f)? 0.0f: mfac/(*rw);
+ float nfac = 1.0f - mfac;
+
+ dz2[0]= fac*dz2[0] + nfac*ro[0];
+ dz2[1]= fac*dz2[1] + nfac*ro[1];
+ dz2[2]= fac*dz2[2] + nfac*ro[2];
+ dz2[3]= fac*dz2[3] + nfac*ro[3];
+ }
+
+ MEM_freeN(rectz);
+ MEM_freeN(rectmove);
+ MEM_freeN(rectdraw);
+ MEM_freeN(rectvz);
+ MEM_freeN(rectweight);
+ MEM_freeN(rectmax);
+ if (minvecbufrect) MEM_freeN(vecbufrect); /* rects were swapped! */
+ zbuf_free_span(&zspan);
+}
diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp
index aa47d3427d0..42fe24120dc 100644
--- a/source/blender/compositor/operations/COM_ViewerOperation.cpp
+++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp
@@ -135,14 +135,14 @@ void ViewerOperation::initImage()
BKE_image_verify_viewer_views(this->m_rd, ima, this->m_imageUser);
}
- BLI_lock_thread(LOCK_DRAW_IMAGE);
+ BLI_thread_lock(LOCK_DRAW_IMAGE);
/* local changes to the original ImageUser */
iuser.multi_index = BKE_scene_multiview_view_id_get(this->m_rd, this->m_viewName);
ibuf = BKE_image_acquire_ibuf(ima, &iuser, &lock);
if (!ibuf) {
- BLI_unlock_thread(LOCK_DRAW_IMAGE);
+ BLI_thread_unlock(LOCK_DRAW_IMAGE);
return;
}
if (ibuf->x != (int)getWidth() || ibuf->y != (int)getHeight()) {
@@ -176,7 +176,7 @@ void ViewerOperation::initImage()
BKE_image_release_ibuf(this->m_image, this->m_ibuf, lock);
- BLI_unlock_thread(LOCK_DRAW_IMAGE);
+ BLI_thread_unlock(LOCK_DRAW_IMAGE);
}
void ViewerOperation::updateImage(rcti *rect)
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt
index c42d06bd0a2..8f6eee244f7 100644
--- a/source/blender/depsgraph/CMakeLists.txt
+++ b/source/blender/depsgraph/CMakeLists.txt
@@ -42,14 +42,13 @@ set(INC_SYS
set(SRC
intern/builder/deg_builder.cc
intern/builder/deg_builder_cycle.cc
+ intern/builder/deg_builder_map.cc
intern/builder/deg_builder_nodes.cc
- intern/builder/deg_builder_nodes_layer_collection.cc
intern/builder/deg_builder_nodes_rig.cc
intern/builder/deg_builder_nodes_view_layer.cc
intern/builder/deg_builder_pchanmap.cc
intern/builder/deg_builder_relations.cc
intern/builder/deg_builder_relations_keys.cc
- intern/builder/deg_builder_relations_layer_collection.cc
intern/builder/deg_builder_relations_rig.cc
intern/builder/deg_builder_relations_view_layer.cc
intern/builder/deg_builder_transitive.cc
@@ -81,6 +80,7 @@ set(SRC
intern/builder/deg_builder.h
intern/builder/deg_builder_cycle.h
+ intern/builder/deg_builder_map.h
intern/builder/deg_builder_nodes.h
intern/builder/deg_builder_pchanmap.h
intern/builder/deg_builder_relations.h
diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h
index 4d3f36b5fba..4760c88cdbd 100644
--- a/source/blender/depsgraph/DEG_depsgraph.h
+++ b/source/blender/depsgraph/DEG_depsgraph.h
@@ -86,7 +86,6 @@ typedef struct EvaluationContext {
struct Depsgraph *depsgraph;
struct ViewLayer *view_layer;
- struct RenderEngineType *engine_type;
} EvaluationContext;
/* DagNode->eval_flags */
@@ -118,7 +117,9 @@ void DEG_depsgraph_enable_copy_on_write(void);
/* Create new Depsgraph instance */
// TODO: what args are needed here? What's the building-graph entry point?
-Depsgraph *DEG_graph_new(void);
+Depsgraph *DEG_graph_new(struct Scene *scene,
+ struct ViewLayer *view_layer,
+ eEvaluationMode mode);
/* Free Depsgraph itself and all its data */
void DEG_graph_free(Depsgraph *graph);
@@ -213,11 +214,22 @@ struct EvaluationContext *DEG_evaluation_context_new(eEvaluationMode mode);
*/
void DEG_evaluation_context_init(struct EvaluationContext *eval_ctx,
eEvaluationMode mode);
-void DEG_evaluation_context_init_from_scene(struct EvaluationContext *eval_ctx,
- struct Scene *scene,
- struct ViewLayer *view_layer,
- struct RenderEngineType *engine_type,
- eEvaluationMode mode);
+void DEG_evaluation_context_init_from_scene(
+ struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ eEvaluationMode mode);
+
+void DEG_evaluation_context_init_from_view_layer_for_render(
+ struct EvaluationContext *eval_ctx,
+ struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct ViewLayer *view_layer);
+
+void DEG_evaluation_context_init_from_depsgraph(
+ struct EvaluationContext *eval_ctx,
+ struct Depsgraph *depsgraph,
+ eEvaluationMode mode);
/* Free evaluation context. */
void DEG_evaluation_context_free(struct EvaluationContext *eval_ctx);
@@ -228,16 +240,14 @@ void DEG_evaluation_context_free(struct EvaluationContext *eval_ctx);
* < context_type: context to perform evaluation for
* < ctime: (frame) new frame to evaluate values on
*/
-void DEG_evaluate_on_framechange(struct EvaluationContext *eval_ctx,
- struct Main *bmain,
+void DEG_evaluate_on_framechange(struct Main *bmain,
Depsgraph *graph,
float ctime);
/* Data changed recalculation entry point.
* < context_type: context to perform evaluation for
*/
-void DEG_evaluate_on_refresh(struct EvaluationContext *eval_ctx,
- Depsgraph *graph);
+void DEG_evaluate_on_refresh(Depsgraph *graph);
bool DEG_needs_eval(Depsgraph *graph);
@@ -264,6 +274,32 @@ typedef void (*DEG_EditorUpdateSceneCb)(
void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func,
DEG_EditorUpdateSceneCb scene_func);
+/* Evaluation Debug ------------------------------ */
+
+void DEG_debug_print_eval(const char* function_name,
+ const char* object_name,
+ const void* object_address);
+
+void DEG_debug_print_eval_subdata(const char *function_name,
+ const char *object_name,
+ const void *object_address,
+ const char *subdata_comment,
+ const char *subdata_name,
+ const void *subdata_address);
+
+void DEG_debug_print_eval_subdata_index(const char *function_name,
+ const char *object_name,
+ const void *object_address,
+ const char *subdata_comment,
+ const char *subdata_name,
+ const void *subdata_address,
+ const int subdata_index);
+
+void DEG_debug_print_eval_time(const char* function_name,
+ const char* object_name,
+ const void* object_address,
+ float time);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h
index adfda27117e..ceba87338a0 100644
--- a/source/blender/depsgraph/DEG_depsgraph_query.h
+++ b/source/blender/depsgraph/DEG_depsgraph_query.h
@@ -49,6 +49,22 @@ struct ViewLayer;
extern "C" {
#endif
+/* *********************** DEG input data ********************* */
+
+/* Get scene that depsgraph was built for. */
+struct Scene *DEG_get_input_scene(const Depsgraph *graph);
+
+/* Get view layer that depsgraph was built for. */
+struct ViewLayer *DEG_get_input_view_layer(const Depsgraph *graph);
+
+/* Get evaluation mode that depsgraph was built for. */
+eEvaluationMode DEG_get_mode(const Depsgraph *graph);
+
+/* Get time that depsgraph is being evaluated or was last evaluated at. */
+float DEG_get_ctime(const Depsgraph *graph);
+
+/* ********************* DEG evaluated data ******************* */
+
/* Check if given ID type was tagged for update. */
bool DEG_id_type_tagged(struct Main *bmain, short id_type);
@@ -86,11 +102,13 @@ typedef enum eDepsObjectIteratorMode {
typedef struct DEGObjectIterData {
struct Depsgraph *graph;
+ eDepsObjectIteratorMode mode;
+ int flag;
+
struct Scene *scene;
struct EvaluationContext eval_ctx;
- int flag;
- eDepsObjectIteratorMode mode;
+ int visibility_check; /* eObjectVisibilityCheck. */
/* **** Iteration over dupli-list. *** */
@@ -123,12 +141,12 @@ void DEG_iterator_objects_end(struct BLI_Iterator *iter);
* Although they are available they have no overrides (collection_properties)
* and will crash if you try to access it.
*/
-#define DEG_OBJECT_ITER(graph_, instance_, mode_, flag_) \
+#define DEG_OBJECT_ITER_BEGIN(graph_, instance_, mode_, flag_) \
{ \
DEGObjectIterData data_ = { \
- .graph = (graph_), \
- .mode = (mode_), \
- .flag = (flag_), \
+ graph_, \
+ mode_, \
+ flag_ \
}; \
\
ITER_BEGIN(DEG_iterator_objects_begin, \
@@ -137,20 +155,20 @@ void DEG_iterator_objects_end(struct BLI_Iterator *iter);
&data_, Object *, instance_)
#define DEG_OBJECT_ITER_END \
- ITER_END \
+ ITER_END; \
}
/**
* Depsgraph objects iterator for draw manager and final render
*/
-#define DEG_OBJECT_ITER_FOR_RENDER_ENGINE(graph_, instance_, mode_) \
- DEG_OBJECT_ITER(graph_, instance_, mode_, \
- DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | \
- DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | \
- DEG_ITER_OBJECT_FLAG_VISIBLE | \
+#define DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(graph_, instance_, mode_) \
+ DEG_OBJECT_ITER_BEGIN(graph_, instance_, mode_, \
+ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | \
+ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | \
+ DEG_ITER_OBJECT_FLAG_VISIBLE | \
DEG_ITER_OBJECT_FLAG_DUPLI)
-#define DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END \
+#define DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END \
DEG_OBJECT_ITER_END
/* ************************ DEG traversal ********************* */
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
index e30b9b44490..026aa309b02 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
@@ -46,6 +46,8 @@
namespace DEG {
+namespace {
+
typedef enum eCyclicCheckVisitedState {
/* Not is not visited at all during traversal. */
NODE_NOT_VISITED = 0,
@@ -55,6 +57,30 @@ typedef enum eCyclicCheckVisitedState {
NODE_IN_STACK = 2,
} eCyclicCheckVisitedState;
+struct StackEntry {
+ OperationDepsNode *node;
+ StackEntry *from;
+ DepsRelation *via_relation;
+};
+
+struct CyclesSolverState {
+ CyclesSolverState(Depsgraph *graph)
+ : graph(graph),
+ traversal_stack(BLI_stack_new(sizeof(StackEntry),
+ "DEG detect cycles stack")),
+ num_cycles(0) {
+ }
+ ~CyclesSolverState() {
+ BLI_stack_free(traversal_stack);
+ if (num_cycles != 0) {
+ printf("Detected %d dependency cycles\n", num_cycles);
+ }
+ }
+ Depsgraph *graph;
+ BLI_Stack *traversal_stack;
+ int num_cycles;
+};
+
BLI_INLINE void set_node_visited_state(DepsNode *node,
eCyclicCheckVisitedState state)
{
@@ -76,18 +102,20 @@ BLI_INLINE int get_node_num_visited_children(DepsNode *node)
return node->done >> 2;
}
-void deg_graph_detect_cycles(Depsgraph *graph)
+void schedule_node_to_stack(CyclesSolverState *state, OperationDepsNode *node)
{
- struct StackEntry {
- OperationDepsNode *node;
- StackEntry *from;
- DepsRelation *via_relation;
- };
-
- BLI_Stack *traversal_stack = BLI_stack_new(sizeof(StackEntry),
- "DEG detect cycles stack");
+ StackEntry entry;
+ entry.node = node;
+ entry.from = NULL;
+ entry.via_relation = NULL;
+ BLI_stack_push(state->traversal_stack, &entry);
+ set_node_visited_state(node, NODE_IN_STACK);
+}
- foreach (OperationDepsNode *node, graph->operations) {
+/* Schedule leaf nodes (node without input links) for traversal. */
+void schedule_leaf_nodes(CyclesSolverState *state)
+{
+ foreach (OperationDepsNode *node, state->graph->operations) {
bool has_inlinks = false;
foreach (DepsRelation *rel, node->inlinks) {
if (rel->from->type == DEG_NODE_TYPE_OPERATION) {
@@ -96,18 +124,32 @@ void deg_graph_detect_cycles(Depsgraph *graph)
}
node->done = 0;
if (has_inlinks == false) {
- StackEntry entry;
- entry.node = node;
- entry.from = NULL;
- entry.via_relation = NULL;
- BLI_stack_push(traversal_stack, &entry);
- set_node_visited_state(node, NODE_IN_STACK);
+ schedule_node_to_stack(state, node);
}
else {
set_node_visited_state(node, NODE_NOT_VISITED);
}
}
+}
+
+/* Schedule node which was not checked yet for being belong to
+ * any of dependency cycle.
+ */
+bool schedule_non_checked_node(CyclesSolverState *state)
+{
+ foreach (OperationDepsNode *node, state->graph->operations) {
+ if (get_node_visited_state(node) == NODE_NOT_VISITED) {
+ schedule_node_to_stack(state, node);
+ return true;
+ }
+ }
+ return false;
+}
+/* Solve cycles with all nodes which are scheduled for traversal. */
+void solve_cycles(CyclesSolverState *state)
+{
+ BLI_Stack *traversal_stack = state->traversal_stack;
while (!BLI_stack_is_empty(traversal_stack)) {
StackEntry *entry = (StackEntry *)BLI_stack_peek(traversal_stack);
OperationDepsNode *node = entry->node;
@@ -136,6 +178,7 @@ void deg_graph_detect_cycles(Depsgraph *graph)
}
/* TODO(sergey): So called russian roulette cycle solver. */
rel->flag |= DEPSREL_FLAG_CYCLIC;
+ ++state->num_cycles;
}
else if (to_state == NODE_NOT_VISITED) {
StackEntry new_entry;
@@ -155,8 +198,24 @@ void deg_graph_detect_cycles(Depsgraph *graph)
BLI_stack_discard(traversal_stack);
}
}
+}
+
+} // namespace
- BLI_stack_free(traversal_stack);
+void deg_graph_detect_cycles(Depsgraph *graph)
+{
+ CyclesSolverState state(graph);
+ /* First we solve cycles which are reachable from leaf nodes. */
+ schedule_leaf_nodes(&state);
+ solve_cycles(&state);
+ /* We are not done yet. It is possible to have closed loop cycle,
+ * for example A -> B -> C -> A. These nodes were not scheduled
+ * yet (since they all have inlinks), and were not traversed since
+ * nobody else points to them.
+ */
+ while (schedule_non_checked_node(&state)) {
+ solve_cycles(&state);
+ }
}
} // namespace DEG
diff --git a/source/blender/modifiers/intern/MOD_boolean_util.h b/source/blender/depsgraph/intern/builder/deg_builder_map.cc
index 00d7c37b266..67cb04d1b98 100644
--- a/source/blender/modifiers/intern/MOD_boolean_util.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_map.cc
@@ -15,32 +15,50 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) Blender Foundation.
+ * The Original Code is Copyright (C) 2018 Blender Foundation.
* All rights reserved.
*
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
+ * Original Author: Sergey Sharybin
+ * Contributor(s): None Yet
*
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/modifiers/intern/MOD_boolean_util.h
- * \ingroup modifiers
+/** \file blender/depsgraph/intern/builder/deg_builder_map.cc
+ * \ingroup depsgraph
*/
+#include "intern/builder/deg_builder_map.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
+namespace DEG {
+
+BuilderMap::BuilderMap() {
+ set = BLI_gset_ptr_new("deg builder gset");
+}
+
-#ifndef __MOD_BOOLEAN_UTIL_H__
-#define __MOD_BOOLEAN_UTIL_H__
+BuilderMap::~BuilderMap() {
+ BLI_gset_free(set, NULL);
+}
-struct Object;
-struct DerivedMesh;
+bool BuilderMap::checkIsBuilt(ID *id) {
+ return BLI_gset_haskey(set, id);
+}
-/* Performs a boolean between two mesh objects, it is assumed that both objects
- * are in fact mesh object. On success returns a DerivedMesh. On failure
- * returns NULL and reports an error. */
+void BuilderMap::tagBuild(ID *id) {
+ BLI_gset_insert(set, id);
+}
-struct DerivedMesh *NewBooleanDerivedMesh(struct DerivedMesh *dm, struct Object *ob,
- struct DerivedMesh *dm_select, struct Object *ob_select, int int_op_type);
+bool BuilderMap::checkIsBuiltAndTag(ID *id) {
+ void **key_p;
+ if (!BLI_gset_ensure_p_ex(set, id, &key_p)) {
+ *key_p = id;
+ return false;
+ }
+ return true;
+}
-#endif /* MOD_BOOLEAN_UTILS */
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_map.h b/source/blender/depsgraph/intern/builder/deg_builder_map.h
new file mode 100644
index 00000000000..5ad22a9aa77
--- /dev/null
+++ b/source/blender/depsgraph/intern/builder/deg_builder_map.h
@@ -0,0 +1,69 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2018 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Sergey Sharybin
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/builder/deg_builder_map.h
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+struct GSet;
+struct ID;
+
+namespace DEG {
+
+class BuilderMap {
+public:
+ BuilderMap();
+ ~BuilderMap();
+
+ /* Check whether given ID is already handled by builder (or if it's being
+ * handled).
+ */
+ bool checkIsBuilt(ID *id);
+
+ /* Tag given ID as handled/built. */
+ void tagBuild(ID *id);
+
+ /* Combination of previous two functions, returns truth if ID was already
+ * handled, or tags is handled otherwise and return false.
+ */
+ bool checkIsBuiltAndTag(ID *id);
+
+ template<typename T> bool checkIsBuilt(T *datablock) {
+ return checkIsBuilt(&datablock->id);
+ }
+ template<typename T> void tagBuild(T *datablock) {
+ tagBuild(&datablock->id);
+ }
+ template<typename T> bool checkIsBuiltAndTag(T *datablock) {
+ return checkIsBuiltAndTag(&datablock->id);
+ }
+
+ GSet *set;
+};
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 0ddb9fd3f28..994674f95fe 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -92,6 +92,7 @@ extern "C" {
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_particle.h"
+#include "BKE_pointcache.h"
#include "BKE_rigidbody.h"
#include "BKE_sound.h"
#include "BKE_tracking.h"
@@ -119,43 +120,11 @@ namespace DEG {
namespace {
-struct BuilderWalkUserData {
- DepsgraphNodeBuilder *builder;
-};
-
-static void modifier_walk(void *user_data,
- struct Object * /*object*/,
- struct Object **obpoin,
- int /*cb_flag*/)
-{
- BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
- if (*obpoin) {
- data->builder->build_object(NULL,
- *obpoin,
- DEG_ID_LINKED_INDIRECTLY);
- }
-}
-
-void constraint_walk(bConstraint * /*con*/,
- ID **idpoin,
- bool /*is_reference*/,
- void *user_data)
-{
- BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
- if (*idpoin) {
- ID *id = *idpoin;
- if (GS(id->name) == ID_OB) {
- data->builder->build_object(NULL,
- (Object *)id,
- DEG_ID_LINKED_INDIRECTLY);
- }
- }
-}
-
void free_copy_on_write_datablock(void *id_v)
{
ID *id = (ID *)id_v;
deg_free_copy_on_write_datablock(id);
+ MEM_freeN(id);
}
} /* namespace */
@@ -169,6 +138,7 @@ DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph)
: bmain_(bmain),
graph_(graph),
scene_(NULL),
+ view_layer_(NULL),
cow_id_hash_(NULL)
{
}
@@ -180,10 +150,10 @@ DepsgraphNodeBuilder::~DepsgraphNodeBuilder()
}
}
-IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id, bool do_tag)
+IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id)
{
if (!DEG_depsgraph_use_copy_on_write()) {
- return graph_->add_id_node(id, do_tag);
+ return graph_->add_id_node(id);
}
IDDepsNode *id_node = NULL;
ID *id_cow = (ID *)BLI_ghash_lookup(cow_id_hash_, id);
@@ -193,12 +163,12 @@ IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id, bool do_tag)
*/
BLI_ghash_remove(cow_id_hash_, id, NULL, NULL);
}
- id_node = graph_->add_id_node(id, do_tag, id_cow);
+ id_node = graph_->add_id_node(id, id_cow);
/* Currently all ID nodes are supposed to have copy-on-write logic.
*
* NOTE: Zero number of components indicates that ID node was just created.
*/
- if (BLI_ghash_size(id_node->components) == 0) {
+ if (BLI_ghash_len(id_node->components) == 0) {
ComponentDepsNode *comp_cow =
id_node->add_component(DEG_NODE_TYPE_COPY_ON_WRITE);
OperationDepsNode *op_cow = comp_cow->add_operation(
@@ -286,6 +256,22 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
name_tag);
}
+OperationDepsNode *DepsgraphNodeBuilder::ensure_operation_node(
+ ID *id,
+ eDepsNode_Type comp_type,
+ const DepsEvalOperationCb& op,
+ eDepsOperation_Code opcode,
+ const char *name,
+ int name_tag)
+{
+ OperationDepsNode *operation =
+ find_operation_node(id, comp_type, opcode, name, name_tag);
+ if (operation != NULL) {
+ return operation;
+ }
+ return add_operation_node(id, comp_type, op, opcode, name, name_tag);
+}
+
bool DepsgraphNodeBuilder::has_operation_node(ID *id,
eDepsNode_Type comp_type,
const char *comp_name,
@@ -334,41 +320,13 @@ ID *DepsgraphNodeBuilder::ensure_cow_id(ID *id_orig)
/* ID is already remapped to copy-on-write. */
return id_orig;
}
- IDDepsNode *id_node = add_id_node(id_orig, false);
- return id_node->id_cow;
-}
-
-ID *DepsgraphNodeBuilder::expand_cow_id(IDDepsNode *id_node)
-{
- return deg_expand_copy_on_write_datablock(graph_, id_node, this, true);
-}
-
-ID *DepsgraphNodeBuilder::expand_cow_id(ID *id_orig)
-{
IDDepsNode *id_node = add_id_node(id_orig);
- return expand_cow_id(id_node);
+ return id_node->id_cow;
}
/* **** Build functions for entity nodes **** */
void DepsgraphNodeBuilder::begin_build() {
- /* LIB_TAG_DOIT is used to indicate whether node for given ID was already
- * created or not. This flag is being set in add_id_node(), so functions
- * shouldn't bother with setting it, they only might query this flag when
- * needed.
- */
- BKE_main_id_tag_all(bmain_, LIB_TAG_DOIT, false);
- /* XXX nested node trees are not included in tag-clearing above,
- * so we need to do this manually.
- */
- FOREACH_NODETREE(bmain_, nodetree, id)
- {
- if (id != (ID *)nodetree) {
- nodetree->id.tag &= ~LIB_TAG_DOIT;
- }
- }
- FOREACH_NODETREE_END;
-
if (DEG_depsgraph_use_copy_on_write()) {
/* Store existing copy-on-write versions of datablock, so we can re-use
* them for new ID nodes.
@@ -376,6 +334,9 @@ void DepsgraphNodeBuilder::begin_build() {
cow_id_hash_ = BLI_ghash_ptr_new("Depsgraph id hash");
foreach (IDDepsNode *id_node, graph_->id_nodes) {
if (deg_copy_on_write_is_expanded(id_node->id_cow)) {
+ if (id_node->id_orig == id_node->id_cow) {
+ continue;
+ }
BLI_ghash_insert(cow_id_hash_,
id_node->id_orig,
id_node->id_cow);
@@ -425,14 +386,12 @@ void DepsgraphNodeBuilder::end_build()
void DepsgraphNodeBuilder::build_group(Group *group)
{
- ID *group_id = &group->id;
- if (group_id->tag & LIB_TAG_DOIT) {
+ if (built_map_.checkIsBuiltAndTag(group)) {
return;
}
- group_id->tag |= LIB_TAG_DOIT;
/* Build group objects. */
- BLI_LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) {
- build_object(NULL, base->object, DEG_ID_LINKED_INDIRECTLY);
+ LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) {
+ build_object(-1, base->object, DEG_ID_LINKED_INDIRECTLY);
}
/* Operation to evaluate the whole view layer.
*
@@ -440,50 +399,50 @@ void DepsgraphNodeBuilder::build_group(Group *group)
* This way we wouldn't need to worry about possible relations from DONE,
* regardless whether it's a group or scene or something else.
*/
- add_id_node(group_id);
+ add_id_node(&group->id);
Group *group_cow = get_cow_datablock(group);
- add_operation_node(group_id,
+ add_operation_node(&group->id,
DEG_NODE_TYPE_LAYER_COLLECTIONS,
function_bind(BKE_group_eval_view_layers,
_1,
group_cow),
- DEG_OPCODE_VIEW_LAYER_DONE);
+ DEG_OPCODE_VIEW_LAYER_EVAL);
}
-void DepsgraphNodeBuilder::build_object(Base *base,
+void DepsgraphNodeBuilder::build_object(int base_index,
Object *object,
eDepsNode_LinkedState_Type linked_state)
{
+ const bool has_object = built_map_.checkIsBuiltAndTag(object);
/* Skip rest of components if the ID node was already there. */
- if (object->id.tag & LIB_TAG_DOIT) {
+ if (has_object) {
IDDepsNode *id_node = find_id_node(&object->id);
/* We need to build some extra stuff if object becomes linked
* directly.
*/
if (id_node->linked_state == DEG_ID_LINKED_INDIRECTLY) {
- build_object_flags(base, object, linked_state);
+ build_object_flags(base_index, object, linked_state);
}
id_node->linked_state = max(id_node->linked_state, linked_state);
return;
}
- object->id.tag |= LIB_TAG_DOIT;
/* Create ID node for object and begin init. */
IDDepsNode *id_node = add_id_node(&object->id);
id_node->linked_state = linked_state;
object->customdata_mask = 0;
/* Various flags, flushing from bases/collections. */
- build_object_flags(base, object, linked_state);
+ build_object_flags(base_index, object, linked_state);
/* Transform. */
build_object_transform(object);
/* Parent. */
if (object->parent != NULL) {
- build_object(NULL, object->parent, DEG_ID_LINKED_INDIRECTLY);
+ build_object(-1, object->parent, DEG_ID_LINKED_INDIRECTLY);
}
/* Modifiers. */
if (object->modifiers.first != NULL) {
BuilderWalkUserData data;
data.builder = this;
- modifiers_foreachObjectLink(object, modifier_walk, &data);
+ modifiers_foreachIDLink(object, modifier_walk, &data);
}
/* Constraints. */
if (object->constraints.first != NULL) {
@@ -499,6 +458,11 @@ void DepsgraphNodeBuilder::build_object(Base *base,
* on object's level animation, for example in case of rebuilding
* pose for proxy.
*/
+ OperationDepsNode *op_node = add_operation_node(&object->id,
+ DEG_NODE_TYPE_PARAMETERS,
+ NULL,
+ DEG_OPCODE_PARAMETERS_EVAL);
+ op_node->set_as_exit();
build_animdata(&object->id);
/* Particle systems. */
if (object->particlesystem.first != NULL) {
@@ -511,7 +475,7 @@ void DepsgraphNodeBuilder::build_object(Base *base,
/* Object that this is a proxy for. */
if (object->proxy) {
object->proxy->proxy_from = object;
- build_object(NULL, object->proxy, DEG_ID_LINKED_INDIRECTLY);
+ build_object(-1, object->proxy, DEG_ID_LINKED_INDIRECTLY);
}
/* Object dupligroup. */
if (object->dup_group != NULL) {
@@ -520,11 +484,11 @@ void DepsgraphNodeBuilder::build_object(Base *base,
}
void DepsgraphNodeBuilder::build_object_flags(
- Base *base,
+ int base_index,
Object *object,
eDepsNode_LinkedState_Type linked_state)
{
- if (base == NULL) {
+ if (base_index == -1) {
return;
}
/* TODO(sergey): Is this really best component to be used? */
@@ -533,7 +497,9 @@ void DepsgraphNodeBuilder::build_object_flags(
add_operation_node(&object->id,
DEG_NODE_TYPE_LAYER_COLLECTIONS,
function_bind(BKE_object_eval_flush_base_flags,
- _1, object_cow, base, is_from_set),
+ _1,
+ object_cow, base_index,
+ is_from_set),
DEG_OPCODE_OBJECT_BASE_FLAGS);
}
@@ -583,7 +549,7 @@ void DepsgraphNodeBuilder::build_object_data(Object *object)
default:
{
ID *obdata = (ID *)object->data;
- if ((obdata->tag & LIB_TAG_DOIT) == 0) {
+ if (built_map_.checkIsBuilt(obdata) == 0) {
build_animdata(obdata);
}
break;
@@ -702,7 +668,7 @@ void DepsgraphNodeBuilder::build_animdata(ID *id)
}
/* drivers */
- BLI_LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
+ LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
/* create driver */
build_driver(id, fcu);
}
@@ -714,50 +680,69 @@ void DepsgraphNodeBuilder::build_animdata(ID *id)
* \param id: ID-Block that driver is attached to
* \param fcu: Driver-FCurve
*/
-OperationDepsNode *DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcu)
+void DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcurve)
{
ID *id_cow = get_cow_id(id);
/* Create data node for this driver */
- /* TODO(sergey): Avoid creating same operation multiple times,
- * in the future we need to avoid lookup of the operation as well
- * and use some tagging magic instead.
- */
- OperationDepsNode *driver_op = find_operation_node(
- id,
- DEG_NODE_TYPE_PARAMETERS,
- DEG_OPCODE_DRIVER,
- fcu->rna_path ? fcu->rna_path : "",
- fcu->array_index);
-
- if (driver_op == NULL) {
- /* TODO(sergey): Shall we use COW of fcu itself here? */
- driver_op = add_operation_node(id,
- DEG_NODE_TYPE_PARAMETERS,
- function_bind(BKE_animsys_eval_driver,
- _1,
- id_cow,
- fcu),
- DEG_OPCODE_DRIVER,
- fcu->rna_path ? fcu->rna_path : "",
- fcu->array_index);
+ /* TODO(sergey): Shall we use COW of fcu itself here? */
+ ensure_operation_node(id,
+ DEG_NODE_TYPE_PARAMETERS,
+ function_bind(BKE_animsys_eval_driver, _1, id_cow, fcurve),
+ DEG_OPCODE_DRIVER,
+ fcurve->rna_path ? fcurve->rna_path : "",
+ fcurve->array_index);
+ build_driver_variables(id, fcurve);
+}
+
+void DepsgraphNodeBuilder::build_driver_variables(ID * id, FCurve *fcurve)
+{
+ build_driver_id_property(id, fcurve->rna_path);
+ LISTBASE_FOREACH (DriverVar *, dvar, &fcurve->driver->variables) {
+ DRIVER_TARGETS_USED_LOOPER(dvar)
+ {
+ build_driver_id_property(dtar->id, dtar->rna_path);
+ }
+ DRIVER_TARGETS_LOOPER_END
}
+}
- /* return driver node created */
- return driver_op;
+void DepsgraphNodeBuilder::build_driver_id_property(ID *id,
+ const char *rna_path)
+{
+ if (id == NULL || rna_path == NULL) {
+ return;
+ }
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ RNA_id_pointer_create(id, &id_ptr);
+ if (!RNA_path_resolve_full(&id_ptr, rna_path, &ptr, &prop, NULL)) {
+ return;
+ }
+ if (prop == NULL) {
+ return;
+ }
+ if (!RNA_property_is_idprop(prop)) {
+ return;
+ }
+ const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop);
+ ensure_operation_node(id,
+ DEG_NODE_TYPE_PARAMETERS,
+ NULL,
+ DEG_OPCODE_ID_PROPERTY,
+ prop_identifier);
}
/* Recursively build graph for world */
void DepsgraphNodeBuilder::build_world(World *world)
{
- ID *world_id = &world->id;
- if (world_id->tag & LIB_TAG_DOIT) {
+ if (built_map_.checkIsBuiltAndTag(world)) {
return;
}
/* Animation. */
- build_animdata(world_id);
+ build_animdata(&world->id);
/* world itself */
- add_operation_node(world_id,
+ add_operation_node(&world->id,
DEG_NODE_TYPE_SHADING,
function_bind(BKE_world_eval,
_1,
@@ -820,7 +805,7 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene)
/* objects - simulation participants */
if (rbw->group) {
- BLI_LISTBASE_FOREACH (Base *, base, &rbw->group->view_layer->object_bases) {
+ LISTBASE_FOREACH (Base *, base, &rbw->group->view_layer->object_bases) {
Object *object = base->object;
if (!object || (object->type != OB_MESH))
@@ -856,8 +841,7 @@ void DepsgraphNodeBuilder::build_particles(Object *object)
* blackbox evaluation step for one particle system referenced by
* the particle systems stack. All dependencies link to this operation.
*/
-
- /* component for all particle systems */
+ /* Component for all particle systems. */
ComponentDepsNode *psys_comp =
add_component_node(&object->id, DEG_NODE_TYPE_EVAL_PARTICLES);
@@ -871,54 +855,57 @@ void DepsgraphNodeBuilder::build_particles(Object *object)
scene_cow,
ob_cow),
DEG_OPCODE_PARTICLE_SYSTEM_EVAL_INIT);
-
- /* particle systems */
- BLI_LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
+ /* Build all particle systems. */
+ LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
ParticleSettings *part = psys->part;
-
/* Build particle settings operations.
*
* NOTE: The call itself ensures settings are only build once.
*/
build_particle_settings(part);
-
- /* Update on particle settings change. */
- add_operation_node(psys_comp,
- function_bind(BKE_particle_system_settings_eval,
- _1,
- psys),
- DEG_OPCODE_PARTICLE_SETTINGS_EVAL,
- psys->name);
-
/* Particle system evaluation. */
add_operation_node(psys_comp,
NULL,
DEG_OPCODE_PARTICLE_SYSTEM_EVAL,
psys->name);
+ /* Visualization of particle system. */
+ switch (part->ren_as) {
+ case PART_DRAW_OB:
+ if (part->dup_ob != NULL) {
+ build_object(-1,
+ part->dup_ob,
+ DEG_ID_LINKED_INDIRECTLY);
+ }
+ break;
+ case PART_DRAW_GR:
+ if (part->dup_group != NULL) {
+ build_group(part->dup_group);
+ }
+ break;
+ }
}
/* TODO(sergey): Do we need a point cache operations here? */
+ add_operation_node(&object->id,
+ DEG_NODE_TYPE_CACHE,
+ function_bind(BKE_ptcache_object_reset,
+ scene_cow,
+ ob_cow,
+ PTCACHE_RESET_DEPSGRAPH),
+ DEG_OPCODE_POINT_CACHE_RESET);
}
void DepsgraphNodeBuilder::build_particle_settings(ParticleSettings *part) {
- ID *part_id = &part->id;
- if (part_id->tag & LIB_TAG_DOIT) {
+ if (built_map_.checkIsBuiltAndTag(part)) {
return;
}
- part_id->tag |= LIB_TAG_DOIT;
/* Animation data. */
- build_animdata(part_id);
+ build_animdata(&part->id);
/* Parameters change. */
- add_operation_node(part_id,
+ add_operation_node(&part->id,
DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PARTICLE_SETTINGS_EVAL);
- add_operation_node(part_id,
- DEG_NODE_TYPE_PARAMETERS,
- function_bind(BKE_particle_system_settings_recalc_clear,
- _1,
- part),
- DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR);
}
void DepsgraphNodeBuilder::build_cloth(Object *object)
@@ -952,17 +939,6 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
Scene *scene_cow = get_cow_datablock(scene_);
Object *object_cow = get_cow_datablock(object);
- /* TODO(sergey): This way using this object's properties as driver target
- * works fine.
- *
- * Does this depend on other nodes?
- */
- op_node = add_operation_node(&object->id,
- DEG_NODE_TYPE_PARAMETERS,
- NULL,
- DEG_OPCODE_PARAMETERS_EVAL);
- op_node->set_as_exit();
-
/* Temporary uber-update node, which does everything.
* It is for the being we're porting old dependencies into the new system.
* We'll get rid of this node as soon as all the granular update functions
@@ -989,7 +965,7 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
// TODO: "Done" operation
/* Cloth modifier. */
- BLI_LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
+ LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
if (md->type == eModifierType_Cloth) {
build_cloth(object);
}
@@ -1020,10 +996,9 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
}
ID *obdata = (ID *)object->data;
- if (obdata->tag & LIB_TAG_DOIT) {
+ if (built_map_.checkIsBuiltAndTag(obdata)) {
return;
}
- obdata->tag |= LIB_TAG_DOIT;
/* Make sure we've got an ID node before requesting CoW pointer. */
(void) add_id_node((ID *)obdata);
ID *obdata_cow = get_cow_id(obdata);
@@ -1103,13 +1078,13 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
*/
Curve *cu = (Curve *)obdata;
if (cu->bevobj != NULL) {
- build_object(NULL, cu->bevobj, DEG_ID_LINKED_INDIRECTLY);
+ build_object(-1, cu->bevobj, DEG_ID_LINKED_INDIRECTLY);
}
if (cu->taperobj != NULL) {
- build_object(NULL, cu->taperobj, DEG_ID_LINKED_INDIRECTLY);
+ build_object(-1, cu->taperobj, DEG_ID_LINKED_INDIRECTLY);
}
if (object->type == OB_FONT && cu->textoncurve != NULL) {
- build_object(NULL, cu->textoncurve, DEG_ID_LINKED_INDIRECTLY);
+ build_object(-1, cu->textoncurve, DEG_ID_LINKED_INDIRECTLY);
}
break;
}
@@ -1164,24 +1139,14 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
/* Cameras */
void DepsgraphNodeBuilder::build_camera(Object *object)
{
- /* Object itself. */
- add_operation_node(&object->id,
- DEG_NODE_TYPE_PARAMETERS,
- NULL,
- DEG_OPCODE_PARAMETERS_EVAL,
- "Camera Parameters");
-
/* Object data. */
- /* TODO: Link scene-camera links in somehow. */
- Camera *cam = (Camera *)object->data;
- ID *camera_id = &cam->id;
- if (camera_id->tag & LIB_TAG_DOIT) {
+ /* TODO: Link scene-camera links in somehow... */
+ Camera *camera = (Camera *)object->data;
+ if (built_map_.checkIsBuiltAndTag(camera)) {
return;
}
-
- build_animdata(&cam->id);
-
- add_operation_node(camera_id,
+ build_animdata(&camera->id);
+ add_operation_node(&camera->id,
DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PARAMETERS_EVAL);
@@ -1190,34 +1155,20 @@ void DepsgraphNodeBuilder::build_camera(Object *object)
/* Lamps */
void DepsgraphNodeBuilder::build_lamp(Object *object)
{
- /* Object itself. */
- add_operation_node(&object->id,
- DEG_NODE_TYPE_PARAMETERS,
- NULL,
- DEG_OPCODE_PARAMETERS_EVAL,
- "Lamp Parameters");
-
/* Object data. */
- Lamp *la = (Lamp *)object->data;
- ID *lamp_id = &la->id;
- if (lamp_id->tag & LIB_TAG_DOIT) {
+ Lamp *lamp = (Lamp *)object->data;
+ if (built_map_.checkIsBuiltAndTag(lamp)) {
return;
}
-
- build_animdata(&la->id);
-
- add_operation_node(lamp_id,
+ build_animdata(&lamp->id);
+ add_operation_node(&lamp->id,
DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PARAMETERS_EVAL);
-
/* lamp's nodetree */
- if (la->nodetree) {
- build_nodetree(la->nodetree);
- }
-
+ build_nodetree(lamp->nodetree);
/* textures */
- build_texture_stack(la->mtex);
+ build_texture_stack(lamp->mtex);
}
void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
@@ -1225,21 +1176,23 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
if (ntree == NULL) {
return;
}
+ if (built_map_.checkIsBuiltAndTag(ntree)) {
+ return;
+ }
/* nodetree itself */
- ID *ntree_id = &ntree->id;
- add_id_node(ntree_id);
+ add_id_node(&ntree->id);
bNodeTree *ntree_cow = get_cow_datablock(ntree);
/* Animation, */
- build_animdata(ntree_id);
+ build_animdata(&ntree->id);
/* Shading update. */
- add_operation_node(ntree_id,
+ add_operation_node(&ntree->id,
DEG_NODE_TYPE_SHADING,
NULL,
DEG_OPCODE_MATERIAL_UPDATE);
/* NOTE: We really pass original and CoW node trees here, this is how the
* callback works. Ideally we need to find a better way for that.
*/
- add_operation_node(ntree_id,
+ add_operation_node(&ntree->id,
DEG_NODE_TYPE_SHADING_PARAMETERS,
function_bind(BKE_nodetree_shading_params_eval,
_1,
@@ -1247,7 +1200,7 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
ntree),
DEG_OPCODE_MATERIAL_UPDATE);
/* nodetree's nodes... */
- BLI_LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
+ LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
ID *id = bnode->id;
if (id == NULL) {
continue;
@@ -1263,7 +1216,7 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
build_image((Image *)id);
}
else if (id_type == ID_OB) {
- build_object(NULL, (Object *)id, DEG_ID_LINKED_INDIRECTLY);
+ build_object(-1, (Object *)id, DEG_ID_LINKED_INDIRECTLY);
}
else if (id_type == ID_SCE) {
/* Scenes are used by compositor trees, and handled by render
@@ -1275,9 +1228,7 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
}
else if (bnode->type == NODE_GROUP) {
bNodeTree *group_ntree = (bNodeTree *)id;
- if ((group_ntree->id.tag & LIB_TAG_DOIT) == 0) {
- build_nodetree(group_ntree);
- }
+ build_nodetree(group_ntree);
}
else {
BLI_assert(!"Unknown ID type used for node");
@@ -1290,23 +1241,21 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
/* Recursively build graph for material */
void DepsgraphNodeBuilder::build_material(Material *material)
{
- ID *material_id = &material->id;
- if (material_id->tag & LIB_TAG_DOIT) {
+ if (built_map_.checkIsBuiltAndTag(material)) {
return;
}
- material_id->tag |= LIB_TAG_DOIT;
/* Material itself. */
- add_id_node(material_id);
+ add_id_node(&material->id);
Material *material_cow = get_cow_datablock(material);
/* Shading update. */
- add_operation_node(material_id,
+ add_operation_node(&material->id,
DEG_NODE_TYPE_SHADING,
function_bind(BKE_material_eval,
_1,
material_cow),
DEG_OPCODE_MATERIAL_UPDATE);
/* Material animation. */
- build_animdata(material_id);
+ build_animdata(&material->id);
/* Textures. */
build_texture_stack(material->mtex);
/* Material's nodetree. */
@@ -1326,33 +1275,34 @@ void DepsgraphNodeBuilder::build_texture_stack(MTex **texture_stack)
}
/* Recursively build graph for texture */
-void DepsgraphNodeBuilder::build_texture(Tex *tex)
+void DepsgraphNodeBuilder::build_texture(Tex *texture)
{
- ID *tex_id = &tex->id;
- if (tex_id->tag & LIB_TAG_DOIT) {
+ if (built_map_.checkIsBuiltAndTag(texture)) {
return;
}
- tex_id->tag |= LIB_TAG_DOIT;
/* Texture itself. */
- build_animdata(tex_id);
+ build_animdata(&texture->id);
/* Texture's nodetree. */
- build_nodetree(tex->nodetree);
+ build_nodetree(texture->nodetree);
/* Special cases for different IDs which texture uses. */
- if (tex->type == TEX_IMAGE) {
- if (tex->ima != NULL) {
- build_image(tex->ima);
+ if (texture->type == TEX_IMAGE) {
+ if (texture->ima != NULL) {
+ build_image(texture->ima);
}
}
+ /* Placeholder so we can add relations and tag ID node for update. */
+ add_operation_node(&texture->id,
+ DEG_NODE_TYPE_PARAMETERS,
+ NULL,
+ DEG_OPCODE_PLACEHOLDER);
}
void DepsgraphNodeBuilder::build_image(Image *image) {
- ID *image_id = &image->id;
- if (image_id->tag & LIB_TAG_DOIT) {
+ if (built_map_.checkIsBuiltAndTag(image)) {
return;
}
- image_id->tag |= LIB_TAG_DOIT;
/* Placeholder so we can add relations and tag ID node for update. */
- add_operation_node(image_id,
+ add_operation_node(&image->id,
DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PLACEHOLDER,
@@ -1431,13 +1381,11 @@ void DepsgraphNodeBuilder::build_movieclip(MovieClip *clip)
void DepsgraphNodeBuilder::build_lightprobe(Object *object)
{
LightProbe *probe = (LightProbe *)object->data;
- ID *probe_id = &probe->id;
- if (probe_id->tag & LIB_TAG_DOIT) {
+ if (built_map_.checkIsBuiltAndTag(probe)) {
return;
}
- probe_id->tag |= LIB_TAG_DOIT;
/* Placeholder so we can add relations and tag ID node for update. */
- add_operation_node(probe_id,
+ add_operation_node(&probe->id,
DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PLACEHOLDER,
@@ -1448,7 +1396,56 @@ void DepsgraphNodeBuilder::build_lightprobe(Object *object)
DEG_OPCODE_PLACEHOLDER,
"LightProbe Eval");
- build_animdata(probe_id);
+ build_animdata(&probe->id);
+}
+
+/* **** ID traversal callbacks functions **** */
+
+void DepsgraphNodeBuilder::modifier_walk(void *user_data,
+ struct Object * /*object*/,
+ struct ID **idpoin,
+ int /*cb_flag*/)
+{
+ BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
+ ID *id = *idpoin;
+ if (id == NULL) {
+ return;
+ }
+ switch (GS(id->name)) {
+ case ID_OB:
+ data->builder->build_object(-1,
+ (Object *)id,
+ DEG_ID_LINKED_INDIRECTLY);
+ break;
+ case ID_TE:
+ data->builder->build_texture((Tex *)id);
+ break;
+ default:
+ /* pass */
+ break;
+ }
+}
+
+void DepsgraphNodeBuilder::constraint_walk(bConstraint * /*con*/,
+ ID **idpoin,
+ bool /*is_reference*/,
+ void *user_data)
+{
+ BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
+ ID *id = *idpoin;
+ if (id == NULL) {
+ return;
+ }
+ switch (GS(id->name)) {
+ case ID_OB:
+ data->builder->build_object(-1,
+ (Object *)id,
+ DEG_ID_LINKED_INDIRECTLY);
+ break;
+ default:
+ /* pass */
+ break;
+ }
}
} // 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 1482f7d947d..c933e139758 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -30,6 +30,7 @@
#pragma once
+#include "intern/builder/deg_builder_map.h"
#include "intern/depsgraph_types.h"
#include "DEG_depsgraph.h" /* used for DEG_depsgraph_use_copy_on_write() */
@@ -89,16 +90,6 @@ struct DepsgraphNodeBuilder {
return (T *)get_cow_id(&orig->id);
}
- /* Get fully expanded (ready for use) copy-on-write datablock for the given
- * original datablock.
- */
- ID *expand_cow_id(IDDepsNode *id_node);
- ID *expand_cow_id(ID *id_orig);
- template<typename T>
- T *expand_cow_datablock(T *orig) {
- return (T *)expand_cow_id(&orig->id);
- }
-
/* For a given COW datablock get corresponding original one. */
template<typename T>
T *get_orig_datablock(const T *cow) const {
@@ -113,7 +104,7 @@ struct DepsgraphNodeBuilder {
void begin_build();
void end_build();
- IDDepsNode *add_id_node(ID *id, bool do_tag = true);
+ IDDepsNode *add_id_node(ID *id);
IDDepsNode *find_id_node(ID *id);
TimeSourceDepsNode *add_time_source();
@@ -140,6 +131,13 @@ struct DepsgraphNodeBuilder {
const char *name = "",
int name_tag = -1);
+ OperationDepsNode *ensure_operation_node(ID *id,
+ eDepsNode_Type comp_type,
+ const DepsEvalOperationCb& op,
+ eDepsOperation_Code opcode,
+ const char *name = "",
+ int name_tag = -1);
+
bool has_operation_node(ID *id,
eDepsNode_Type comp_type,
const char *comp_name,
@@ -164,22 +162,24 @@ struct DepsgraphNodeBuilder {
ViewLayer *view_layer,
eDepsNode_LinkedState_Type linked_state);
void build_group(Group *group);
- void build_object(Base *base,
+ void build_object(int base_index,
Object *object,
eDepsNode_LinkedState_Type linked_state);
- void build_object_flags(Base *base,
+ void build_object_flags(int base_index,
Object *object,
eDepsNode_LinkedState_Type linked_state);
void build_object_data(Object *object);
void build_object_transform(Object *object);
void build_object_constraints(Object *object);
- void build_pose_constraints(Object *object, bPoseChannel *pchan);
+ void build_pose_constraints(Object *object, bPoseChannel *pchan, int pchan_index);
void build_rigidbody(Scene *scene);
void build_particles(Object *object);
void build_particle_settings(ParticleSettings *part);
void build_cloth(Object *object);
void build_animdata(ID *id);
- OperationDepsNode *build_driver(ID *id, FCurve *fcurve);
+ void build_driver(ID *id, FCurve *fcurve);
+ void build_driver_variables(ID *id, FCurve *fcurve);
+ void build_driver_id_property(ID *id, const char *rna_path);
void build_ik_pose(Object *object,
bPoseChannel *pchan,
bConstraint *con);
@@ -205,17 +205,6 @@ struct DepsgraphNodeBuilder {
void build_movieclip(MovieClip *clip);
void build_lightprobe(Object *object);
- struct LayerCollectionState {
- int index;
- LayerCollection *parent;
- };
- void build_layer_collection(ID *owner_id,
- LayerCollection *layer_collection,
- LayerCollectionState *state);
- void build_layer_collections(ID *owner_id,
- ListBase *layer_collections,
- LayerCollectionState *state);
- void build_view_layer_collections(ID *owner_id, ViewLayer *view_layer);
protected:
struct SavedEntryTag {
ID *id;
@@ -224,14 +213,30 @@ protected:
};
vector<SavedEntryTag> saved_entry_tags_;
+ struct BuilderWalkUserData {
+ DepsgraphNodeBuilder *builder;
+ };
+
+ static void modifier_walk(void *user_data,
+ struct Object *object,
+ struct ID **idpoin,
+ int cb_flag);
+
+ static void constraint_walk(bConstraint *constraint,
+ ID **idpoin,
+ bool is_reference,
+ void *user_data);
+
/* State which never changes, same for the whole builder time. */
Main *bmain_;
Depsgraph *graph_;
/* State which demotes currently built entities. */
Scene *scene_;
+ ViewLayer *view_layer_;
GHash *cow_id_hash_;
+ BuilderMap built_map_;
};
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc
deleted file mode 100644
index 137a79e7276..00000000000
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2013 Blender Foundation.
- * All rights reserved.
- *
- * Original Author: Joshua Leung
- * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013)
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc
- * \ingroup depsgraph
- *
- * Methods for constructing depsgraph's nodes
- */
-
-#include "intern/builder/deg_builder_nodes.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "MEM_guardedalloc.h"
-
-extern "C" {
-#include "BLI_utildefines.h"
-#include "BLI_listbase.h"
-#include "BLI_string.h"
-
-#include "BKE_layer.h"
-
-#include "DNA_scene_types.h"
-
-#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_build.h"
-} /* extern "C" */
-
-#include "intern/builder/deg_builder.h"
-#include "intern/eval/deg_eval_copy_on_write.h"
-#include "intern/nodes/deg_node.h"
-#include "intern/nodes/deg_node_component.h"
-#include "intern/nodes/deg_node_operation.h"
-#include "intern/depsgraph_types.h"
-#include "intern/depsgraph_intern.h"
-#include "util/deg_util_foreach.h"
-
-namespace DEG {
-
-void DepsgraphNodeBuilder::build_layer_collection(
- ID *owner_id,
- LayerCollection *layer_collection,
- LayerCollectionState *state)
-{
- /* TODO(sergey): This will attempt to create component for each collection.
- * Harmless but could be optimized.
- */
- ComponentDepsNode *comp = add_component_node(
- owner_id,
- DEG_NODE_TYPE_LAYER_COLLECTIONS);
-
- add_operation_node(comp,
- function_bind(BKE_layer_eval_layer_collection,
- _1,
- layer_collection,
- state->parent),
- DEG_OPCODE_VIEW_LAYER_EVAL,
- layer_collection->scene_collection->name,
- state->index);
- ++state->index;
-
- /* Recurs into nested layer collections. */
- LayerCollection *parent = state->parent;
- state->parent = layer_collection;
- build_layer_collections(owner_id, &layer_collection->layer_collections, state);
- state->parent = parent;
-}
-
-void DepsgraphNodeBuilder::build_layer_collections(ID *owner_id,
- ListBase *layer_collections,
- LayerCollectionState *state)
-{
- BLI_LISTBASE_FOREACH (LayerCollection *, layer_collection, layer_collections) {
- build_layer_collection(owner_id, layer_collection, state);
- }
-}
-
-void DepsgraphNodeBuilder::build_view_layer_collections(
- ID *owner_id,
- ViewLayer *view_layer)
-{
- LayerCollectionState state;
- state.index = 0;
- ComponentDepsNode *comp = add_component_node(
- owner_id,
- DEG_NODE_TYPE_LAYER_COLLECTIONS);
- add_operation_node(comp,
- function_bind(BKE_layer_eval_layer_collection_pre,
- _1,
- owner_id,
- view_layer),
- DEG_OPCODE_VIEW_LAYER_INIT);
- add_operation_node(comp,
- function_bind(BKE_layer_eval_layer_collection_post,
- _1,
- view_layer),
- DEG_OPCODE_VIEW_LAYER_DONE);
- state.parent = NULL;
- build_layer_collections(owner_id, &view_layer->layer_collections, &state);
-}
-
-} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
index 2fc42efa440..208462713a5 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
@@ -50,6 +50,7 @@ extern "C" {
#include "BKE_action.h"
#include "BKE_armature.h"
+#include "BKE_constraint.h"
} /* extern "C" */
#include "DEG_depsgraph.h"
@@ -67,15 +68,20 @@ extern "C" {
namespace DEG {
void DepsgraphNodeBuilder::build_pose_constraints(Object *object,
- bPoseChannel *pchan)
+ bPoseChannel *pchan,
+ int pchan_index)
{
- /* create node for constraint stack */
+ /* Pull indirect dependencies via constraints. */
+ BuilderWalkUserData data;
+ data.builder = this;
+ BKE_constraints_id_loop(&pchan->constraints, constraint_walk, &data);
+ /* Create node for constraint stack. */
add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
function_bind(BKE_pose_constraints_evaluate,
_1,
get_cow_datablock(scene_),
get_cow_datablock(object),
- pchan),
+ pchan_index),
DEG_OPCODE_BONE_CONSTRAINTS);
}
@@ -98,13 +104,15 @@ void DepsgraphNodeBuilder::build_ik_pose(Object *object,
return;
}
+ int rootchan_index = BLI_findindex(&object->pose->chanbase, rootchan);
+ BLI_assert(rootchan_index != -1);
/* Operation node for evaluating/running IK Solver. */
add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
function_bind(BKE_pose_iktree_evaluate,
_1,
get_cow_datablock(scene_),
get_cow_datablock(object),
- rootchan),
+ rootchan_index),
DEG_OPCODE_POSE_IK_SOLVER);
}
@@ -122,12 +130,14 @@ void DepsgraphNodeBuilder::build_splineik_pose(Object *object,
* Store the "root bone" of this chain in the solver, so it knows where to
* start.
*/
+ int rootchan_index = BLI_findindex(&object->pose->chanbase, rootchan);
+ BLI_assert(rootchan_index != -1);
add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
function_bind(BKE_pose_splineik_evaluate,
_1,
get_cow_datablock(scene_),
get_cow_datablock(object),
- rootchan),
+ rootchan_index),
DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
}
@@ -135,22 +145,15 @@ void DepsgraphNodeBuilder::build_splineik_pose(Object *object,
void DepsgraphNodeBuilder::build_rig(Object *object)
{
bArmature *armature = (bArmature *)object->data;
- const short armature_tag = armature->id.tag;
Scene *scene_cow;
Object *object_cow;
- bArmature *armature_cow;
if (DEG_depsgraph_use_copy_on_write()) {
- /* NOTE: We need to expand both object and armature, so this way we can
- * safely create object level pose.
- */
scene_cow = get_cow_datablock(scene_);
- object_cow = expand_cow_datablock(object);
- armature_cow = expand_cow_datablock(armature);
+ object_cow = get_cow_datablock(object);
}
else {
scene_cow = scene_;
object_cow = object;
- armature_cow = armature;
}
OperationDepsNode *op_node;
@@ -163,9 +166,8 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
* mechanism in-between here to ensure that we can use same rig
* multiple times in same scene.
*/
- if ((armature_tag & LIB_TAG_DOIT) == 0) {
+ if (!built_map_.checkIsBuilt(armature)) {
build_animdata(&armature->id);
-
/* Make sure pose is up-to-date with armature updates. */
add_operation_node(&armature->id,
DEG_NODE_TYPE_PARAMETERS,
@@ -175,22 +177,22 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
}
/* Rebuild pose if not up to date. */
- if (object_cow->pose == NULL || (object->pose->flag & POSE_RECALC)) {
- BKE_pose_rebuild(object_cow, armature_cow);
+ if (object->pose == NULL || (object->pose->flag & POSE_RECALC)) {
+ BKE_pose_rebuild(object, armature);
/* XXX: Without this animation gets lost in certain circumstances
* after loading file. Need to investigate further since it does
* not happen with simple scenes..
*/
- if (object_cow->adt) {
- object_cow->adt->recalc |= ADT_RECALC_ANIM;
+ if (object->adt) {
+ object->adt->recalc |= ADT_RECALC_ANIM;
}
}
/* speed optimization for animation lookups */
- if (object_cow->pose != NULL) {
- BKE_pose_channels_hash_make(object_cow->pose);
- if (object_cow->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
- BKE_pose_update_constraint_flags(object_cow->pose);
+ if (object->pose != NULL) {
+ BKE_pose_channels_hash_make(object->pose);
+ if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
+ BKE_pose_update_constraint_flags(object->pose);
}
}
@@ -222,8 +224,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
function_bind(BKE_pose_eval_init,
_1,
scene_cow,
- object_cow,
- object_cow->pose),
+ object_cow),
DEG_OPCODE_POSE_INIT);
op_node->set_as_entry();
@@ -232,8 +233,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
function_bind(BKE_pose_eval_init_ik,
_1,
scene_cow,
- object_cow,
- object_cow->pose),
+ object_cow),
DEG_OPCODE_POSE_INIT_IK);
op_node = add_operation_node(&object->id,
@@ -241,13 +241,13 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
function_bind(BKE_pose_eval_flush,
_1,
scene_cow,
- object_cow,
- object_cow->pose),
+ object_cow),
DEG_OPCODE_POSE_DONE);
op_node->set_as_exit();
/* bones */
- BLI_LISTBASE_FOREACH (bPoseChannel *, pchan, &object_cow->pose->chanbase) {
+ int pchan_index = 0;
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
/* Node for bone evaluation. */
op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name, NULL,
DEG_OPCODE_BONE_LOCAL);
@@ -257,7 +257,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
function_bind(BKE_pose_eval_bone, _1,
scene_cow,
object_cow,
- pchan),
+ pchan_index),
DEG_OPCODE_BONE_POSE_PARENT);
/* NOTE: Dedicated noop for easier relationship construction. */
@@ -266,7 +266,10 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
DEG_OPCODE_BONE_READY);
op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
- function_bind(BKE_pose_bone_done, _1, pchan),
+ function_bind(BKE_pose_bone_done,
+ _1,
+ object_cow,
+ pchan_index),
DEG_OPCODE_BONE_DONE);
op_node->set_as_exit();
/* Custom properties. */
@@ -279,7 +282,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
}
/* Build constraints. */
if (pchan->constraints.first != NULL) {
- build_pose_constraints(object, pchan);
+ build_pose_constraints(object, pchan, pchan_index);
}
/**
* IK Solvers.
@@ -293,7 +296,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
* as in ik-tree building
* - Animated chain-lengths are a problem.
*/
- BLI_LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
+ LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
switch (con->type) {
case CONSTRAINT_TYPE_KINEMATIC:
build_ik_pose(object, pchan, con);
@@ -307,13 +310,13 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
break;
}
}
+
/* Custom shape. */
- /* NOTE: Custom shape datablock is already remapped to CoW version. */
if (pchan->custom != NULL) {
- build_object(NULL,
- get_orig_datablock(pchan->custom),
- DEG_ID_LINKED_INDIRECTLY);
+ build_object(-1, pchan->custom, DEG_ID_LINKED_INDIRECTLY);
}
+
+ pchan_index++;
}
}
@@ -323,10 +326,7 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
OperationDepsNode *op_node;
Object *object_cow;
if (DEG_depsgraph_use_copy_on_write()) {
- /* NOTE: We need to expand both object and armature, so this way we can
- * safely create object level pose.
- */
- object_cow = expand_cow_datablock(object);
+ object_cow = get_cow_datablock(object);
}
else {
object_cow = object;
@@ -337,8 +337,8 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
build_animdata(&arm->id);
/* speed optimization for animation lookups */
BKE_pose_channels_hash_make(object->pose);
- if (object_cow->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
- BKE_pose_update_constraint_flags(object_cow->pose);
+ if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
+ BKE_pose_update_constraint_flags(object->pose);
}
op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_EVAL_POSE,
@@ -347,8 +347,8 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
object_cow),
DEG_OPCODE_POSE_INIT);
op_node->set_as_entry();
- BLI_LISTBASE_FOREACH (bPoseChannel *, pchan, &object_cow->pose->chanbase) {
- /* Local bone transform. */
+
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_BONE,
pchan->name,
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
index 4ca19f4e14f..390619aeeaa 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
@@ -76,35 +76,14 @@ void DepsgraphNodeBuilder::build_view_layer(
add_time_source();
/* Setup currently building context. */
scene_ = scene;
- /* Expand Scene Cow datablock to get proper pointers to bases. */
+ view_layer_ = view_layer;
+ /* Get pointer to a CoW version of scene ID. */
Scene *scene_cow;
- ViewLayer *view_layer_cow;
if (DEG_depsgraph_use_copy_on_write()) {
- /* NOTE: We need to create ID nodes for all objects coming from bases,
- * otherwise remapping will not replace objects with their CoW versions
- * for CoW bases.
- */
- BLI_LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
- Object *object = base->object;
- add_id_node(&object->id, false);
- }
- /* Create ID node for nested ID of nodetree as well, otherwise remapping
- * will not work correct either.
- */
- if (scene->nodetree != NULL) {
- add_id_node(&scene->nodetree->id, false);
- }
- /* Make sure we've got ID node, so we can get pointer to CoW datablock.
- */
- scene_cow = expand_cow_datablock(scene);
- view_layer_cow = (ViewLayer *)BLI_findstring(
- &scene_cow->view_layers,
- view_layer->name,
- offsetof(ViewLayer, name));
+ scene_cow = get_cow_datablock(scene);
}
else {
scene_cow = scene;
- view_layer_cow = view_layer;
}
/* Scene objects. */
int select_color = 1;
@@ -112,17 +91,15 @@ void DepsgraphNodeBuilder::build_view_layer(
* but object is expected to be an original one. Hence we go into some
* tricks here iterating over the view layer.
*/
- for (Base *base_orig = (Base *)view_layer->object_bases.first,
- *base_cow = (Base *)view_layer_cow->object_bases.first;
- base_orig != NULL;
- base_orig = base_orig->next, base_cow = base_cow->next)
- {
+ int base_index = 0;
+ LISTBASE_FOREACH(Base *, base, &view_layer->object_bases) {
/* object itself */
- build_object(base_cow, base_orig->object, linked_state);
- base_orig->object->select_color = select_color++;
+ build_object(base_index, base->object, linked_state);
+ base->object->select_color = select_color++;
+ ++base_index;
}
if (scene->camera != NULL) {
- build_object(NULL, scene->camera, DEG_ID_LINKED_INDIRECTLY);
+ build_object(-1, scene->camera, DEG_ID_LINKED_INDIRECTLY);
}
/* Rigidbody. */
if (scene->rigidbody_world != NULL) {
@@ -145,19 +122,27 @@ void DepsgraphNodeBuilder::build_view_layer(
build_gpencil(scene->gpd);
}
/* Cache file. */
- BLI_LISTBASE_FOREACH (CacheFile *, cachefile, &bmain_->cachefiles) {
+ LISTBASE_FOREACH (CacheFile *, cachefile, &bmain_->cachefiles) {
build_cachefile(cachefile);
}
/* Masks. */
- BLI_LISTBASE_FOREACH (Mask *, mask, &bmain_->mask) {
+ LISTBASE_FOREACH (Mask *, mask, &bmain_->mask) {
build_mask(mask);
}
/* Movie clips. */
- BLI_LISTBASE_FOREACH (MovieClip *, clip, &bmain_->movieclip) {
+ LISTBASE_FOREACH (MovieClip *, clip, &bmain_->movieclip) {
build_movieclip(clip);
}
/* Collections. */
- build_view_layer_collections(&scene->id, view_layer_cow);
+ int view_layer_index = BLI_findindex(&scene->view_layers, view_layer);
+ BLI_assert(view_layer_index != -1);
+ add_operation_node(&scene->id,
+ DEG_NODE_TYPE_LAYER_COLLECTIONS,
+ function_bind(BKE_layer_eval_view_layer_indexed,
+ _1,
+ &scene_cow->id,
+ view_layer_index),
+ DEG_OPCODE_VIEW_LAYER_EVAL);
/* Parameters evaluation for scene relations mainly. */
add_operation_node(&scene->id,
DEG_NODE_TYPE_PARAMETERS,
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 04a72f85a78..7da2c4f54a1 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -68,7 +68,7 @@ extern "C" {
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "BKE_action.h"
#include "BKE_armature.h"
@@ -117,39 +117,6 @@ extern "C" {
namespace DEG {
-namespace {
-
-struct BuilderWalkUserData {
- DepsgraphRelationBuilder *builder;
-};
-
-void modifier_walk(void *user_data,
- struct Object * /*object*/,
- struct Object **obpoin,
- int /*cb_flag*/)
-{
- BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
- if (*obpoin) {
- data->builder->build_object(NULL, *obpoin);
- }
-}
-
-void constraint_walk(bConstraint * /*con*/,
- ID **idpoin,
- bool /*is_reference*/,
- void *user_data)
-{
- BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
- if (*idpoin) {
- ID *id = *idpoin;
- if (GS(id->name) == ID_OB) {
- data->builder->build_object(NULL, (Object *)id);
- }
- }
-}
-
-} /* namespace */
-
/* ***************** */
/* Relations Builder */
@@ -196,7 +163,7 @@ static bool particle_system_depends_on_time(ParticleSystem *psys)
static bool object_particles_depends_on_time(Object *object)
{
- BLI_LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
+ LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
if (particle_system_depends_on_time(psys)) {
return true;
}
@@ -285,7 +252,7 @@ void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc,
graph_->add_new_relation(timesrc, node_to, description, check_unique);
}
else {
- DEG_DEBUG_PRINTF("add_time_relation(%p = %s, %p = %s, %s) Failed\n",
+ DEG_DEBUG_PRINTF(BUILD, "add_time_relation(%p = %s, %p = %s, %s) Failed\n",
timesrc, (timesrc) ? timesrc->identifier().c_str() : "<None>",
node_to, (node_to) ? node_to->identifier().c_str() : "<None>",
description);
@@ -302,7 +269,7 @@ void DepsgraphRelationBuilder::add_operation_relation(
graph_->add_new_relation(node_from, node_to, description, check_unique);
}
else {
- DEG_DEBUG_PRINTF("add_operation_relation(%p = %s, %p = %s, %s) Failed\n",
+ DEG_DEBUG_PRINTF(BUILD, "add_operation_relation(%p = %s, %p = %s, %s) Failed\n",
node_from, (node_from) ? node_from->identifier().c_str() : "<None>",
node_to, (node_to) ? node_to->identifier().c_str() : "<None>",
description);
@@ -349,7 +316,7 @@ void DepsgraphRelationBuilder::add_forcefield_relations(
{
ListBase *effectors = pdInitEffectors(NULL, scene, object, psys, eff, false);
if (effectors != NULL) {
- BLI_LISTBASE_FOREACH (EffectorCache *, eff, effectors) {
+ LISTBASE_FOREACH (EffectorCache *, eff, effectors) {
if (eff->ob != object) {
ComponentKey eff_key(&eff->ob->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(eff_key, key, name);
@@ -405,52 +372,35 @@ Depsgraph *DepsgraphRelationBuilder::getGraph()
void DepsgraphRelationBuilder::begin_build()
{
- /* LIB_TAG_DOIT is used to indicate whether node for given ID was already
- * created or not.
- */
- BKE_main_id_tag_all(bmain_, LIB_TAG_DOIT, false);
- /* XXX nested node trees are notr included in tag-clearing above,
- * so we need to do this manually.
- */
- FOREACH_NODETREE(bmain_, nodetree, id)
- {
- if (id != (ID *)nodetree) {
- nodetree->id.tag &= ~LIB_TAG_DOIT;
- }
- }
- FOREACH_NODETREE_END
}
void DepsgraphRelationBuilder::build_group(Object *object, Group *group)
{
- ID *group_id = &group->id;
- bool group_done = (group_id->tag & LIB_TAG_DOIT) != 0;
- OperationKey object_local_transform_key(&object->id,
+ const bool group_done = built_map_.checkIsBuiltAndTag(group);
+ OperationKey object_local_transform_key(object != NULL ? &object->id : NULL,
DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_LOCAL);
-
if (!group_done) {
- BLI_LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) {
+ LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) {
build_object(NULL, base->object);
}
- group_id->tag |= LIB_TAG_DOIT;
}
-
- BLI_LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) {
- ComponentKey dupli_transform_key(&base->object->id, DEG_NODE_TYPE_TRANSFORM);
- add_relation(dupli_transform_key, object_local_transform_key, "Dupligroup");
+ if (object != NULL) {
+ LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) {
+ ComponentKey dupli_transform_key(&base->object->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(dupli_transform_key, object_local_transform_key, "Dupligroup");
+ }
}
}
void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
{
- if (object->id.tag & LIB_TAG_DOIT) {
+ if (built_map_.checkIsBuiltAndTag(object)) {
if (base != NULL) {
build_object_flags(base, object);
}
return;
}
- object->id.tag |= LIB_TAG_DOIT;
/* Object Transforms */
eDepsOperation_Code base_op = (object->parent) ? DEG_OPCODE_TRANSFORM_PARENT
: DEG_OPCODE_TRANSFORM_LOCAL;
@@ -482,7 +432,7 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
if (object->modifiers.first != NULL) {
BuilderWalkUserData data;
data.builder = this;
- modifiers_foreachObjectLink(object, modifier_walk, &data);
+ modifiers_foreachIDLink(object, modifier_walk, &data);
}
/* Constraints. */
if (object->constraints.first != NULL) {
@@ -557,7 +507,7 @@ void DepsgraphRelationBuilder::build_object_flags(Base *base, Object *object)
}
OperationKey view_layer_done_key(&scene_->id,
DEG_NODE_TYPE_LAYER_COLLECTIONS,
- DEG_OPCODE_VIEW_LAYER_DONE);
+ DEG_OPCODE_VIEW_LAYER_EVAL);
OperationKey object_flags_key(&object->id,
DEG_NODE_TYPE_LAYER_COLLECTIONS,
DEG_OPCODE_OBJECT_BASE_FLAGS);
@@ -779,7 +729,7 @@ void DepsgraphRelationBuilder::build_constraints(ID *id,
else if (cti->get_constraint_targets) {
ListBase targets = {NULL, NULL};
cti->get_constraint_targets(con, &targets);
- BLI_LISTBASE_FOREACH (bConstraintTarget *, ct, &targets) {
+ LISTBASE_FOREACH (bConstraintTarget *, ct, &targets) {
if (ct->tar == NULL) {
continue;
}
@@ -942,18 +892,7 @@ void DepsgraphRelationBuilder::build_animdata_curves(ID *id)
ComponentKey adt_key(id, DEG_NODE_TYPE_ANIMATION);
TimeSourceKey time_src_key;
add_relation(time_src_key, adt_key, "TimeSrc -> Animation");
- /* Build relations from animation operation to properties it changes. */
- build_animdata_curves_targets(id);
-}
-
-void DepsgraphRelationBuilder::build_animdata_curves_targets(ID *id)
-{
- AnimData *adt = BKE_animdata_from_id(id);
- if (adt == NULL || adt->action == NULL) {
- return;
- }
- /* Get source operation. */
- ComponentKey adt_key(id, DEG_NODE_TYPE_ANIMATION);
+ /* Get source operations. */
DepsNode *node_from = get_node(adt_key);
BLI_assert(node_from != NULL);
if (node_from == NULL) {
@@ -961,10 +900,28 @@ void DepsgraphRelationBuilder::build_animdata_curves_targets(ID *id)
}
OperationDepsNode *operation_from = node_from->get_exit_operation();
BLI_assert(operation_from != NULL);
+ /* Build relations from animation operation to properties it changes. */
+ if (adt->action != NULL) {
+ build_animdata_curves_targets(id, adt_key,
+ operation_from,
+ &adt->action->curves);
+ }
+ LISTBASE_FOREACH(NlaTrack *, nlt, &adt->nla_tracks) {
+ build_animdata_nlastrip_targets(id, adt_key,
+ operation_from,
+ &nlt->strips);
+ }
+}
+
+void DepsgraphRelationBuilder::build_animdata_curves_targets(
+ ID *id, ComponentKey &adt_key,
+ OperationDepsNode *operation_from,
+ ListBase *curves)
+{
/* Iterate over all curves and build relations. */
PointerRNA id_ptr;
RNA_id_pointer_create(id, &id_ptr);
- BLI_LISTBASE_FOREACH (FCurve *, fcu, &adt->action->curves) {
+ LISTBASE_FOREACH(FCurve *, fcu, curves) {
PointerRNA ptr;
PropertyRNA *prop;
int index;
@@ -1007,6 +964,25 @@ void DepsgraphRelationBuilder::build_animdata_curves_targets(ID *id)
}
}
+void DepsgraphRelationBuilder::build_animdata_nlastrip_targets(
+ ID *id, ComponentKey &adt_key,
+ OperationDepsNode *operation_from,
+ ListBase *strips)
+{
+ LISTBASE_FOREACH(NlaStrip *, strip, strips) {
+ if (strip->act != NULL) {
+ build_animdata_curves_targets(id, adt_key,
+ operation_from,
+ &strip->act->curves);
+ }
+ else if (strip->strips.first != NULL) {
+ build_animdata_nlastrip_targets(id, adt_key,
+ operation_from,
+ &strip->strips);
+ }
+ }
+}
+
void DepsgraphRelationBuilder::build_animdata_drivers(ID *id)
{
AnimData *adt = BKE_animdata_from_id(id);
@@ -1014,7 +990,7 @@ void DepsgraphRelationBuilder::build_animdata_drivers(ID *id)
return;
}
ComponentKey adt_key(id, DEG_NODE_TYPE_ANIMATION);
- BLI_LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
+ LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
OperationKey driver_key(id,
DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER,
@@ -1037,7 +1013,7 @@ void DepsgraphRelationBuilder::build_animdata_drivers(ID *id)
*/
if (fcu->array_index > 0) {
FCurve *fcu_prev = NULL;
- BLI_LISTBASE_FOREACH (FCurve *, fcu_candidate, &adt->drivers) {
+ LISTBASE_FOREACH (FCurve *, fcu_candidate, &adt->drivers) {
/* Writing to different RNA paths is */
const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
if (!STREQ(fcu_candidate->rna_path, rna_path)) {
@@ -1172,6 +1148,26 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
}
}
}
+ if (RNA_pointer_is_null(&target_key.ptr)) {
+ /* TODO(sergey): This would only mean that driver is broken.
+ * so we can't create relation anyway. However, we need to avoid
+ * adding drivers which are known to be buggy to a dependency
+ * graph, in order to save computational power.
+ */
+ }
+ else {
+ if (target_key.prop != NULL &&
+ RNA_property_is_idprop(target_key.prop))
+ {
+ OperationKey parameters_key(id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PARAMETERS_EVAL);
+ add_relation(target_key,
+ parameters_key,
+ "Driver Target -> Properties");
+ }
+ add_relation(driver_key, target_key, "Driver -> Target");
+ }
}
}
@@ -1186,7 +1182,7 @@ void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
const RNAPathKey self_key(id, rna_path);
- BLI_LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
+ LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
/* Only used targets. */
DRIVER_TARGETS_USED_LOOPER(dvar)
{
@@ -1261,24 +1257,18 @@ void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
void DepsgraphRelationBuilder::build_world(World *world)
{
- ID *world_id = &world->id;
- if (world_id->tag & LIB_TAG_DOIT) {
+ if (built_map_.checkIsBuiltAndTag(world)) {
return;
}
- world_id->tag |= LIB_TAG_DOIT;
-
- build_animdata(world_id);
-
+ build_animdata(&world->id);
/* TODO: other settings? */
-
/* textures */
build_texture_stack(world->mtex);
-
/* world's nodetree */
if (world->nodetree != NULL) {
build_nodetree(world->nodetree);
ComponentKey ntree_key(&world->nodetree->id, DEG_NODE_TYPE_SHADING);
- ComponentKey world_key(world_id, DEG_NODE_TYPE_SHADING);
+ ComponentKey world_key(&world->id, DEG_NODE_TYPE_SHADING);
add_relation(ntree_key, world_key, "NTree->World Shading Update");
}
}
@@ -1301,7 +1291,7 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
/* objects - simulation participants */
if (rbw->group) {
- BLI_LISTBASE_FOREACH (Base *, base, &rbw->group->view_layer->object_bases) {
+ LISTBASE_FOREACH (Base *, base, &rbw->group->view_layer->object_bases) {
Object *object = base->object;
if (object == NULL || object->type != OB_MESH) {
continue;
@@ -1355,7 +1345,7 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
/* constraints */
if (rbw->constraints) {
- BLI_LISTBASE_FOREACH (Base *, base, &rbw->constraints->view_layer->object_bases) {
+ LISTBASE_FOREACH (Base *, base, &rbw->constraints->view_layer->object_bases) {
Object *object = base->object;
if (object == NULL || !object->rigidbody_constraint) {
continue;
@@ -1390,8 +1380,8 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
DEG_NODE_TYPE_EVAL_PARTICLES,
DEG_OPCODE_PARTICLE_SYSTEM_EVAL_INIT);
- /* particle systems */
- BLI_LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
+ /* Particle systems. */
+ LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
ParticleSettings *part = psys->part;
/* Build particle settings relations.
@@ -1410,33 +1400,14 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
OperationKey particle_settings_key(&part->id,
DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_PARTICLE_SETTINGS_EVAL);
- OperationKey particle_settings_recalc_clear_key(
- &part->id,
- DEG_NODE_TYPE_PARAMETERS,
- DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR);
- OperationKey psys_settings_key(&object->id,
- DEG_NODE_TYPE_EVAL_PARTICLES,
- DEG_OPCODE_PARTICLE_SETTINGS_EVAL,
- psys->name);
- add_relation(particle_settings_key, psys_settings_key, "Particle Settings Change");
- add_relation(psys_settings_key, psys_key, "Particle Settings Update");
- add_relation(psys_key,
- particle_settings_recalc_clear_key,
- "Particle Settings Recalc Clear");
-
- /* XXX: if particle system is later re-enabled, we must do full rebuild? */
- if (!psys_check_enabled(object, psys, G.is_rendering))
- continue;
-
+ add_relation(particle_settings_key, eval_init_key, "Particle Settings Change");
add_relation(eval_init_key, psys_key, "Init -> PSys");
-
/* TODO(sergey): Currently particle update is just a placeholder,
* hook it to the ubereval node so particle system is getting updated
* on playback.
*/
add_relation(psys_key, obdata_ubereval_key, "PSys -> UberEval");
-
- /* collisions */
+ /* Collisions */
if (part->type != PART_HAIR) {
add_collision_relations(psys_key,
scene_,
@@ -1456,8 +1427,7 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
true,
"Hair Collision");
}
-
- /* effectors */
+ /* Effectors. */
add_forcefield_relations(psys_key,
scene_,
object,
@@ -1465,35 +1435,46 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
part->effector_weights,
part->type == PART_HAIR,
"Particle Field");
-
- /* boids */
+ /* Boids .*/
if (part->boids) {
- BLI_LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
- BLI_LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
+ LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
+ LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
Object *ruleob = NULL;
- if (rule->type == eBoidRuleType_Avoid)
+ if (rule->type == eBoidRuleType_Avoid) {
ruleob = ((BoidRuleGoalAvoid *)rule)->ob;
- else if (rule->type == eBoidRuleType_FollowLeader)
+ }
+ else if (rule->type == eBoidRuleType_FollowLeader) {
ruleob = ((BoidRuleFollowLeader *)rule)->ob;
-
+ }
if (ruleob) {
- ComponentKey ruleob_key(&ruleob->id, DEG_NODE_TYPE_TRANSFORM);
+ ComponentKey ruleob_key(&ruleob->id,
+ DEG_NODE_TYPE_TRANSFORM);
add_relation(ruleob_key, psys_key, "Boid Rule");
}
}
}
}
-
- if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
- ComponentKey dup_ob_key(&part->dup_ob->id, DEG_NODE_TYPE_TRANSFORM);
- add_relation(dup_ob_key, psys_key, "Particle Object Visualization");
- if (part->dup_ob->type == OB_MBALL) {
- ComponentKey dup_geometry_key(&part->dup_ob->id,
- DEG_NODE_TYPE_GEOMETRY);
- add_relation(obdata_ubereval_key,
- dup_geometry_key,
- "Particle MBall Visualization");
- }
+ switch (part->ren_as) {
+ case PART_DRAW_OB:
+ if (part->dup_ob != NULL) {
+ /* Make sure object's relations are all built. */
+ build_object(NULL, part->dup_ob);
+ /* Build relation for the particle visualization. */
+ build_particles_visualization_object(object,
+ psys,
+ part->dup_ob);
+ }
+ break;
+ case PART_DRAW_GR:
+ if (part->dup_group != NULL) {
+ build_group(NULL, part->dup_group);
+ LISTBASE_FOREACH (GroupObject *, go, &part->dup_group->gobject) {
+ build_particles_visualization_object(object,
+ psys,
+ go->ob);
+ }
+ }
+ break;
}
}
@@ -1506,27 +1487,42 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
ComponentKey transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(transform_key, obdata_ubereval_key, "Partcile Eval");
- /* TODO(sergey): Do we need a point cache operations here? */
+ OperationKey point_cache_reset_key(&object->id,
+ DEG_NODE_TYPE_CACHE,
+ DEG_OPCODE_POINT_CACHE_RESET);
+ add_relation(transform_key, point_cache_reset_key, "Object Transform -> Point Cache Reset");
+ add_relation(point_cache_reset_key, obdata_ubereval_key, "Point Cache Reset -> UberEval");
}
void DepsgraphRelationBuilder::build_particle_settings(ParticleSettings *part)
{
- ID *part_id = &part->id;
- if (part_id->tag & LIB_TAG_DOIT) {
+ if (built_map_.checkIsBuiltAndTag(part)) {
return;
}
- part_id->tag |= LIB_TAG_DOIT;
-
/* Animation data relations. */
build_animdata(&part->id);
+}
- OperationKey eval_key(part_id,
- DEG_NODE_TYPE_PARAMETERS,
- DEG_OPCODE_PARTICLE_SETTINGS_EVAL);
- OperationKey recalc_clear_key(part_id,
- DEG_NODE_TYPE_PARAMETERS,
- DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR);
- add_relation(eval_key, recalc_clear_key, "Particle Settings Clear Recalc");
+void DepsgraphRelationBuilder::build_particles_visualization_object(
+ Object *object,
+ ParticleSystem *psys,
+ Object *draw_object)
+{
+ OperationKey psys_key(&object->id,
+ DEG_NODE_TYPE_EVAL_PARTICLES,
+ DEG_OPCODE_PARTICLE_SYSTEM_EVAL,
+ psys->name);
+ OperationKey obdata_ubereval_key(&object->id,
+ DEG_NODE_TYPE_GEOMETRY,
+ DEG_OPCODE_GEOMETRY_UBEREVAL);
+ ComponentKey dup_ob_key(&draw_object->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(dup_ob_key, psys_key, "Particle Object Visualization");
+ if (draw_object->type == OB_MBALL) {
+ ComponentKey dup_geometry_key(&draw_object->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(obdata_ubereval_key,
+ dup_geometry_key,
+ "Particle MBall Visualization");
+ }
}
void DepsgraphRelationBuilder::build_cloth(Object *object,
@@ -1616,16 +1612,16 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object)
/* Modifiers */
if (object->modifiers.first != NULL) {
- BLI_LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
+ ModifierUpdateDepsgraphContext ctx = {};
+ ctx.scene = scene_;
+ ctx.object = object;
+
+ LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type);
if (mti->updateDepsgraph) {
DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
- mti->updateDepsgraph(
- md,
- bmain_,
- scene_,
- object,
- reinterpret_cast< ::DepsNodeHandle* >(&handle));
+ ctx.node = reinterpret_cast< ::DepsNodeHandle* >(&handle);
+ mti->updateDepsgraph(md, &ctx);
}
if (BKE_object_modifier_use_time(object, md)) {
TimeSourceKey time_src_key;
@@ -1670,10 +1666,9 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object)
add_relation(geom_init_key, obdata_ubereval_key, "Object Geometry UberEval");
}
- if (obdata->tag & LIB_TAG_DOIT) {
+ if (built_map_.checkIsBuiltAndTag(obdata)) {
return;
}
- obdata->tag |= LIB_TAG_DOIT;
/* Link object data evaluation node to exit operation. */
OperationKey obdata_geom_eval_key(obdata, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Geometry Eval");
@@ -1782,22 +1777,20 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object)
// TODO: Link scene-camera links in somehow...
void DepsgraphRelationBuilder::build_camera(Object *object)
{
- Camera *cam = (Camera *)object->data;
- ID *camera_id = &cam->id;
- if (camera_id->tag & LIB_TAG_DOIT) {
+ Camera *camera = (Camera *)object->data;
+ if (built_map_.checkIsBuiltAndTag(camera)) {
return;
}
- camera_id->tag |= LIB_TAG_DOIT;
ComponentKey object_parameters_key(&object->id, DEG_NODE_TYPE_PARAMETERS);
- ComponentKey camera_parameters_key(camera_id, DEG_NODE_TYPE_PARAMETERS);
+ ComponentKey camera_parameters_key(&camera->id, DEG_NODE_TYPE_PARAMETERS);
add_relation(camera_parameters_key, object_parameters_key,
"Camera -> Object");
/* DOF */
- if (cam->dof_ob != NULL) {
- ComponentKey dof_ob_key(&cam->dof_ob->id, DEG_NODE_TYPE_TRANSFORM);
+ if (camera->dof_ob != NULL) {
+ ComponentKey dof_ob_key(&camera->dof_ob->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(dof_ob_key, object_parameters_key, "Camera DOF");
}
}
@@ -1805,27 +1798,25 @@ void DepsgraphRelationBuilder::build_camera(Object *object)
/* Lamps */
void DepsgraphRelationBuilder::build_lamp(Object *object)
{
- Lamp *la = (Lamp *)object->data;
- ID *lamp_id = &la->id;
- if (lamp_id->tag & LIB_TAG_DOIT) {
+ Lamp *lamp = (Lamp *)object->data;
+ if (built_map_.checkIsBuiltAndTag(lamp)) {
return;
}
- lamp_id->tag |= LIB_TAG_DOIT;
ComponentKey object_parameters_key(&object->id, DEG_NODE_TYPE_PARAMETERS);
- ComponentKey lamp_parameters_key(lamp_id, DEG_NODE_TYPE_PARAMETERS);
+ ComponentKey lamp_parameters_key(&lamp->id, DEG_NODE_TYPE_PARAMETERS);
add_relation(lamp_parameters_key, object_parameters_key,
"Lamp -> Object");
/* lamp's nodetree */
- if (la->nodetree != NULL) {
- build_nodetree(la->nodetree);
- ComponentKey nodetree_key(&la->nodetree->id, DEG_NODE_TYPE_SHADING);
+ if (lamp->nodetree != NULL) {
+ build_nodetree(lamp->nodetree);
+ ComponentKey nodetree_key(&lamp->nodetree->id, DEG_NODE_TYPE_SHADING);
add_relation(nodetree_key, lamp_parameters_key, "NTree->Lamp Parameters");
}
/* textures */
- build_texture_stack(la->mtex);
+ build_texture_stack(lamp->mtex);
if (DEG_depsgraph_use_copy_on_write()) {
/* Make sure copy on write of lamp data is always properly updated for
@@ -1834,7 +1825,7 @@ void DepsgraphRelationBuilder::build_lamp(Object *object)
OperationKey ob_copy_on_write_key(&object->id,
DEG_NODE_TYPE_COPY_ON_WRITE,
DEG_OPCODE_COPY_ON_WRITE);
- OperationKey lamp_copy_on_write_key(lamp_id,
+ OperationKey lamp_copy_on_write_key(&lamp->id,
DEG_NODE_TYPE_COPY_ON_WRITE,
DEG_OPCODE_COPY_ON_WRITE);
add_relation(lamp_copy_on_write_key, ob_copy_on_write_key, "Eval Order");
@@ -1846,11 +1837,13 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
if (ntree == NULL) {
return;
}
- ID *ntree_id = &ntree->id;
- build_animdata(ntree_id);
- ComponentKey shading_key(ntree_id, DEG_NODE_TYPE_SHADING);
+ if (built_map_.checkIsBuiltAndTag(ntree)) {
+ return;
+ }
+ build_animdata(&ntree->id);
+ ComponentKey shading_key(&ntree->id, DEG_NODE_TYPE_SHADING);
/* nodetree's nodes... */
- BLI_LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
+ LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
ID *id = bnode->id;
if (id == NULL) {
continue;
@@ -1878,10 +1871,7 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
}
else if (bnode->type == NODE_GROUP) {
bNodeTree *group_ntree = (bNodeTree *)id;
- if ((group_ntree->id.tag & LIB_TAG_DOIT) == 0) {
- build_nodetree(group_ntree);
- group_ntree->id.tag |= LIB_TAG_DOIT;
- }
+ build_nodetree(group_ntree);
ComponentKey group_shading_key(&group_ntree->id,
DEG_NODE_TYPE_SHADING);
add_relation(group_shading_key, shading_key, "Group Node");
@@ -1891,37 +1881,32 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
}
}
- OperationKey shading_update_key(ntree_id,
+ OperationKey shading_update_key(&ntree->id,
DEG_NODE_TYPE_SHADING,
DEG_OPCODE_MATERIAL_UPDATE);
- OperationKey shading_parameters_key(ntree_id,
+ OperationKey shading_parameters_key(&ntree->id,
DEG_NODE_TYPE_SHADING_PARAMETERS,
DEG_OPCODE_MATERIAL_UPDATE);
add_relation(shading_parameters_key, shading_update_key, "NTree Shading Parameters");
}
/* Recursively build graph for material */
-void DepsgraphRelationBuilder::build_material(Material *ma)
+void DepsgraphRelationBuilder::build_material(Material *material)
{
- ID *ma_id = &ma->id;
- if (ma_id->tag & LIB_TAG_DOIT) {
+ if (built_map_.checkIsBuiltAndTag(material)) {
return;
}
- ma_id->tag |= LIB_TAG_DOIT;
-
/* animation */
- build_animdata(ma_id);
-
+ build_animdata(&material->id);
/* textures */
- build_texture_stack(ma->mtex);
-
+ build_texture_stack(material->mtex);
/* material's nodetree */
- if (ma->nodetree != NULL) {
- build_nodetree(ma->nodetree);
- OperationKey ntree_key(&ma->nodetree->id,
+ if (material->nodetree != NULL) {
+ build_nodetree(material->nodetree);
+ OperationKey ntree_key(&material->nodetree->id,
DEG_NODE_TYPE_SHADING,
DEG_OPCODE_MATERIAL_UPDATE);
- OperationKey material_key(&ma->id,
+ OperationKey material_key(&material->id,
DEG_NODE_TYPE_SHADING,
DEG_OPCODE_MATERIAL_UPDATE);
add_relation(ntree_key, material_key, "Material's NTree");
@@ -1929,28 +1914,22 @@ void DepsgraphRelationBuilder::build_material(Material *ma)
}
/* Recursively build graph for texture */
-void DepsgraphRelationBuilder::build_texture(Tex *tex)
+void DepsgraphRelationBuilder::build_texture(Tex *texture)
{
- ID *tex_id = &tex->id;
- if (tex_id->tag & LIB_TAG_DOIT) {
+ if (built_map_.checkIsBuiltAndTag(texture)) {
return;
}
- tex_id->tag |= LIB_TAG_DOIT;
-
/* texture itself */
- build_animdata(tex_id);
-
+ build_animdata(&texture->id);
/* texture's nodetree */
- build_nodetree(tex->nodetree);
+ build_nodetree(texture->nodetree);
}
/* Texture-stack attached to some shading datablock */
void DepsgraphRelationBuilder::build_texture_stack(MTex **texture_stack)
{
- int i;
-
/* for now assume that all texture-stacks have same number of max items */
- for (i = 0; i < MAX_MTEX; i++) {
+ for (int i = 0; i < MAX_MTEX; i++) {
MTex *mtex = texture_stack[i];
if (mtex && mtex->tex)
build_texture(mtex->tex);
@@ -2002,14 +1981,12 @@ void DepsgraphRelationBuilder::build_movieclip(MovieClip *clip)
void DepsgraphRelationBuilder::build_lightprobe(Object *object)
{
LightProbe *probe = (LightProbe *)object->data;
- ID *probe_id = &probe->id;
- if (probe_id->tag & LIB_TAG_DOIT) {
+ if (built_map_.checkIsBuiltAndTag(probe)) {
return;
}
- probe_id->tag |= LIB_TAG_DOIT;
build_animdata(&probe->id);
- OperationKey probe_key(probe_id,
+ OperationKey probe_key(&probe->id,
DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_PLACEHOLDER,
"LightProbe Eval");
@@ -2066,6 +2043,22 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDDepsNode *id_node
if (op_node->inlinks.size() == 0) {
graph_->add_new_relation(op_cow, op_node, "CoW Dependency");
}
+ else {
+ bool has_same_comp_dependency = false;
+ foreach (DepsRelation *rel, op_node->inlinks) {
+ if (rel->from->type != DEG_NODE_TYPE_OPERATION) {
+ continue;
+ }
+ OperationDepsNode *op_node_from = (OperationDepsNode *)rel->from;
+ if (op_node_from->owner == op_node->owner) {
+ has_same_comp_dependency = true;
+ break;
+ }
+ }
+ if (!has_same_comp_dependency) {
+ graph_->add_new_relation(op_cow, op_node, "CoW Dependency");
+ }
+ }
}
GHASH_FOREACH_END();
/* NOTE: We currently ignore implicit relations to an external
@@ -2096,4 +2089,43 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDDepsNode *id_node
}
}
+/* **** ID traversal callbacks functions **** */
+
+void DepsgraphRelationBuilder::modifier_walk(void *user_data,
+ struct Object * /*object*/,
+ struct ID **idpoin,
+ int /*cb_flag*/)
+{
+ BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
+ ID *id = *idpoin;
+ if (id == NULL) {
+ return;
+ }
+ switch (GS(id->name)) {
+ case ID_OB:
+ data->builder->build_object(NULL, (Object *)id);
+ break;
+ case ID_TE:
+ data->builder->build_texture((Tex *)id);
+ break;
+ default:
+ /* pass */
+ break;
+ }
+}
+
+void DepsgraphRelationBuilder::constraint_walk(bConstraint * /*con*/,
+ ID **idpoin,
+ bool /*is_reference*/,
+ void *user_data)
+{
+ BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
+ if (*idpoin) {
+ ID *id = *idpoin;
+ if (GS(id->name) == ID_OB) {
+ data->builder->build_object(NULL, (Object *)id);
+ }
+ }
+}
+
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 1d556f6b2ce..4ddad462a5a 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -43,6 +43,7 @@
#include "BLI_utildefines.h"
#include "BLI_string.h"
+#include "intern/builder/deg_builder_map.h"
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
#include "intern/nodes/deg_node_operation.h"
@@ -67,13 +68,13 @@ struct bNodeTree;
struct Object;
struct bPoseChannel;
struct bConstraint;
+struct ParticleSystem;
+struct ParticleSettings;
struct Scene;
struct ViewLayer;
struct Tex;
struct World;
struct EffectorWeights;
-struct ParticleSystem;
-struct ParticleSettings;
struct Groom;
struct PropertyRNA;
@@ -206,7 +207,14 @@ struct DepsgraphRelationBuilder
RootPChanMap *root_map);
void build_animdata(ID *id);
void build_animdata_curves(ID *id);
- void build_animdata_curves_targets(ID *id);
+ void build_animdata_curves_targets(ID *id,
+ ComponentKey &adt_key,
+ OperationDepsNode *operation_from,
+ ListBase *curves);
+ void build_animdata_nlastrip_targets(ID *id,
+ ComponentKey &adt_key,
+ OperationDepsNode *operation_from,
+ ListBase *strips);
void build_animdata_drivers(ID *id);
void build_driver(ID *id, FCurve *fcurve);
void build_driver_data(ID *id, FCurve *fcurve);
@@ -215,6 +223,9 @@ struct DepsgraphRelationBuilder
void build_rigidbody(Scene *scene);
void build_particles(Object *object);
void build_particle_settings(ParticleSettings *part);
+ void build_particles_visualization_object(Object *object,
+ ParticleSystem *psys,
+ Object *draw_object);
void build_cloth(Object *object, ModifierData *md);
void build_ik_pose(Object *object,
bPoseChannel *pchan,
@@ -254,20 +265,6 @@ struct DepsgraphRelationBuilder
EffectorWeights *eff,
bool add_absorption, const char *name);
- struct LayerCollectionState {
- int index;
- OperationKey init_key;
- OperationKey done_key;
- OperationKey prev_key;
- };
- void build_layer_collection(ID *owner_id,
- LayerCollection *layer_collection,
- LayerCollectionState *state);
- void build_layer_collections(ID *owner_id,
- ListBase *layer_collections,
- LayerCollectionState *state);
- void build_view_layer_collections(struct ID *owner_id, ViewLayer *view_layer);
-
void build_copy_on_write_relations();
void build_copy_on_write_relations(IDDepsNode *id_node);
@@ -324,12 +321,28 @@ protected:
const KeyTo& key_to);
private:
+ struct BuilderWalkUserData {
+ DepsgraphRelationBuilder *builder;
+ };
+
+ static void modifier_walk(void *user_data,
+ struct Object *object,
+ struct ID **idpoin,
+ int cb_flag);
+
+ static void constraint_walk(bConstraint *con,
+ ID **idpoin,
+ bool is_reference,
+ void *user_data);
+
/* State which never changes, same for the whole builder time. */
Main *bmain_;
Depsgraph *graph_;
/* State which demotes currently built entities. */
Scene *scene_;
+
+ BuilderMap built_map_;
};
struct DepsNodeHandle
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc
deleted file mode 100644
index 9cf82b5fb47..00000000000
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2013 Blender Foundation.
- * All rights reserved.
- *
- * Original Author: Joshua Leung
- * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013)
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc
- * \ingroup depsgraph
- *
- * Methods for constructing depsgraph
- */
-
-#include "intern/builder/deg_builder_relations.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <cstring> /* required for STREQ later on. */
-
-#include "MEM_guardedalloc.h"
-
-extern "C" {
-#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
-
-#include "DNA_node_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-
-#include "BKE_layer.h"
-#include "BKE_main.h"
-#include "BKE_node.h"
-
-#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_build.h"
-} /* extern "C" */
-
-#include "intern/builder/deg_builder.h"
-#include "intern/builder/deg_builder_pchanmap.h"
-
-#include "intern/nodes/deg_node.h"
-#include "intern/nodes/deg_node_component.h"
-#include "intern/nodes/deg_node_operation.h"
-
-#include "intern/depsgraph_intern.h"
-#include "intern/depsgraph_types.h"
-
-#include "util/deg_util_foreach.h"
-
-namespace DEG {
-
-void DepsgraphRelationBuilder::build_layer_collection(
- ID *owner_id,
- LayerCollection *layer_collection,
- LayerCollectionState *state)
-{
- OperationKey layer_key(owner_id,
- DEG_NODE_TYPE_LAYER_COLLECTIONS,
- DEG_OPCODE_VIEW_LAYER_EVAL,
- layer_collection->scene_collection->name,
- state->index);
- add_relation(state->prev_key, layer_key, "Layer collection order");
-
- ++state->index;
- state->prev_key = layer_key;
-
- /* Recurs into nested layer collections. */
- build_layer_collections(owner_id, &layer_collection->layer_collections, state);
-}
-
-void DepsgraphRelationBuilder::build_layer_collections(
- ID *owner_id,
- ListBase *layer_collections,
- LayerCollectionState *state)
-{
- BLI_LISTBASE_FOREACH (LayerCollection *, layer_collection, layer_collections) {
- /* Recurs into the layer. */
- build_layer_collection(owner_id, layer_collection, state);
- }
-}
-
-void DepsgraphRelationBuilder::build_view_layer_collections(
- ID *owner_id,
- ViewLayer *view_layer)
-{
- LayerCollectionState state;
- state.index = 0;
-
- OperationKey init_key(owner_id,
- DEG_NODE_TYPE_LAYER_COLLECTIONS,
- DEG_OPCODE_VIEW_LAYER_INIT);
- OperationKey done_key(owner_id,
- DEG_NODE_TYPE_LAYER_COLLECTIONS,
- DEG_OPCODE_VIEW_LAYER_DONE);
-
- state.init_key = init_key;
- state.done_key = done_key;
- state.prev_key = init_key;
-
- build_layer_collections(owner_id, &view_layer->layer_collections, &state);
-
- add_relation(state.prev_key, done_key, "Layer collection order");
-}
-
-} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
index ad812a4b505..c80e0d568f3 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
@@ -51,6 +51,7 @@ extern "C" {
#include "BKE_action.h"
#include "BKE_armature.h"
+#include "BKE_constraint.h"
} /* extern "C" */
#include "DEG_depsgraph.h"
@@ -175,15 +176,12 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *object,
}
}
- DEG_DEBUG_PRINTF("\nStarting IK Build: pchan = %s, target = (%s, %s), segcount = %d\n",
+ DEG_DEBUG_PRINTF(BUILD, "\nStarting IK Build: pchan = %s, target = (%s, %s), segcount = %d\n",
pchan->name, data->tar->id.name, data->subtarget, data->rootbone);
bPoseChannel *parchan = pchan;
/* exclude tip from chain? */
if (!(data->flag & CONSTRAINT_IK_TIP)) {
- OperationKey tip_transforms_key(&object->id, DEG_NODE_TYPE_BONE,
- parchan->name, DEG_OPCODE_BONE_LOCAL);
- add_relation(solver_key, tip_transforms_key, "IK Solver Result");
parchan = pchan->parent;
}
@@ -221,7 +219,7 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *object,
root_map->add_bone(parchan->name, rootchan->name);
/* continue up chain, until we reach target number of items... */
- DEG_DEBUG_PRINTF(" %d = %s\n", segcount, parchan->name);
+ DEG_DEBUG_PRINTF(BUILD, " %d = %s\n", segcount, parchan->name);
segcount++;
if ((segcount == data->rootbone) || (segcount > 255)) break; /* 255 is weak */
@@ -341,8 +339,8 @@ void DepsgraphRelationBuilder::build_rig(Object *object)
*/
RootPChanMap root_map;
bool pose_depends_on_local_transform = false;
- BLI_LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
- BLI_LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
+ LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
switch (con->type) {
case CONSTRAINT_TYPE_KINEMATIC:
build_ik_pose(object, pchan, con, &root_map);
@@ -382,7 +380,7 @@ void DepsgraphRelationBuilder::build_rig(Object *object)
}
/* links between operations for each bone */
- BLI_LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
OperationKey bone_local_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
OperationKey bone_pose_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT);
OperationKey bone_ready_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
@@ -409,6 +407,11 @@ void DepsgraphRelationBuilder::build_rig(Object *object)
}
/* Buil constraints. */
if (pchan->constraints.first != NULL) {
+ /* Build relations for indirectly linked objects. */
+ BuilderWalkUserData data;
+ data.builder = this;
+ BKE_constraints_id_loop(&pchan->constraints, constraint_walk, &data);
+
/* constraints stack and constraint dependencies */
build_constraints(&object->id, DEG_NODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map);
@@ -434,6 +437,7 @@ void DepsgraphRelationBuilder::build_rig(Object *object)
/* assume that all bones must be done for the pose to be ready (for deformers) */
add_relation(bone_done_key, flush_key, "PoseEval Result-Bone Link");
+
/* Custom shape. */
if (pchan->custom != NULL) {
build_object(NULL, pchan->custom);
@@ -443,16 +447,43 @@ void DepsgraphRelationBuilder::build_rig(Object *object)
void DepsgraphRelationBuilder::build_proxy_rig(Object *object)
{
- OperationKey pose_init_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
- OperationKey pose_done_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
- BLI_LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
- OperationKey bone_local_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
- OperationKey bone_ready_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
- OperationKey bone_done_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
+ Object *proxy_from = object->proxy_from;
+ OperationKey pose_init_key(&object->id,
+ DEG_NODE_TYPE_EVAL_POSE,
+ DEG_OPCODE_POSE_INIT);
+ OperationKey pose_done_key(&object->id,
+ DEG_NODE_TYPE_EVAL_POSE,
+ DEG_OPCODE_POSE_DONE);
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
+ OperationKey bone_local_key(&object->id,
+ DEG_NODE_TYPE_BONE, pchan->name,
+ DEG_OPCODE_BONE_LOCAL);
+ OperationKey bone_ready_key(&object->id,
+ DEG_NODE_TYPE_BONE,
+ pchan->name,
+ DEG_OPCODE_BONE_READY);
+ OperationKey bone_done_key(&object->id,
+ DEG_NODE_TYPE_BONE,
+ pchan->name,
+ DEG_OPCODE_BONE_DONE);
add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local");
add_relation(bone_local_key, bone_ready_key, "Local -> Ready");
add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
add_relation(bone_done_key, pose_done_key, "Bone Done -> Pose Done");
+
+ if (pchan->prop != NULL) {
+ OperationKey bone_parameters(&object->id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PARAMETERS_EVAL,
+ pchan->name);
+ OperationKey from_bone_parameters(&proxy_from->id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PARAMETERS_EVAL,
+ pchan->name);
+ add_relation(from_bone_parameters,
+ bone_parameters,
+ "Proxy Bone Parameters");
+ }
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
index cfb98fe2f79..85f465efb82 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
@@ -78,7 +78,7 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la
* passed to the evaluation functions. During relations builder we only
* do NULL-pointer check of the base, so it's fine to pass original one.
*/
- BLI_LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
build_object(base, base->object);
}
if (scene->camera != NULL) {
@@ -105,15 +105,13 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la
build_gpencil(scene->gpd);
}
/* Masks. */
- BLI_LISTBASE_FOREACH (Mask *, mask, &bmain_->mask) {
+ LISTBASE_FOREACH (Mask *, mask, &bmain_->mask) {
build_mask(mask);
}
/* Movie clips. */
- BLI_LISTBASE_FOREACH (MovieClip *, clip, &bmain_->movieclip) {
+ LISTBASE_FOREACH (MovieClip *, clip, &bmain_->movieclip) {
build_movieclip(clip);
}
- /* Collections. */
- build_view_layer_collections(&scene_->id, view_layer);
/* TODO(sergey): Do this flush on CoW object? */
foreach (OperationDepsNode *node, graph_->operations) {
IDDepsNode *id_node = node->owner->owner;
@@ -129,8 +127,8 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la
build_view_layer(scene->set, set_view_layer);
}
- graph_->scene = scene;
- graph_->view_layer = view_layer;
+ BLI_assert(graph_->scene == scene);
+ BLI_assert(graph_->view_layer == view_layer);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
index 7731b76c6b9..12760cad73c 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
@@ -117,7 +117,7 @@ void deg_graph_transitive_reduction(Depsgraph *graph)
}
}
}
- DEG_DEBUG_PRINTF("Removed %d relations\n", num_removed_relations);
+ DEG_DEBUG_PRINTF(BUILD, "Removed %d relations\n", num_removed_relations);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
index 8fc4c0bcec1..ee40ca50ab5 100644
--- a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
+++ b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
@@ -346,7 +346,7 @@ static void deg_debug_graphviz_node(const DebugContext &ctx,
case DEG_NODE_TYPE_ID_REF:
{
const IDDepsNode *id_node = (const IDDepsNode *)node;
- if (BLI_ghash_size(id_node->components) == 0) {
+ if (BLI_ghash_len(id_node->components) == 0) {
deg_debug_graphviz_node_single(ctx, node);
}
else {
@@ -405,7 +405,7 @@ static bool deg_debug_graphviz_is_cluster(const DepsNode *node)
case DEG_NODE_TYPE_ID_REF:
{
const IDDepsNode *id_node = (const IDDepsNode *)node;
- return BLI_ghash_size(id_node->components) > 0;
+ return BLI_ghash_len(id_node->components) > 0;
}
case DEG_NODE_TYPE_PARAMETERS:
case DEG_NODE_TYPE_ANIMATION:
@@ -467,7 +467,7 @@ static void deg_debug_graphviz_node_relations(const DebugContext &ctx,
deg_debug_fprintf(ctx, "[");
/* Note: without label an id seem necessary to avoid bugs in graphviz/dot */
deg_debug_fprintf(ctx, "id=\"%s\"", rel->name);
- deg_debug_fprintf(ctx, "label=\"%s\"", rel->name);
+ // deg_debug_fprintf(ctx, "label=\"%s\"", rel->name);
deg_debug_fprintf(ctx, ",color="); deg_debug_graphviz_relation_color(ctx, rel);
deg_debug_fprintf(ctx, ",penwidth=\"%f\"", penwidth);
/* NOTE: edge from node to own cluster is not possible and gives graphviz
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index 3a78c9050f7..a87358187f2 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -35,6 +35,8 @@
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
+#include "BLI_console.h"
+#include "BLI_hash.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
@@ -47,6 +49,8 @@ extern "C" {
#include "DNA_sequence_types.h"
#include "RNA_access.h"
+
+#include "BKE_scene.h"
}
#include <algorithm>
@@ -90,11 +94,15 @@ static void remove_from_vector(vector<T> *vector, const T& value)
vector->end());
}
-Depsgraph::Depsgraph()
+Depsgraph::Depsgraph(Scene *scene,
+ ViewLayer *view_layer,
+ eEvaluationMode mode)
: time_source(NULL),
need_update(true),
- scene(NULL),
- view_layer(NULL)
+ scene(scene),
+ view_layer(view_layer),
+ mode(mode),
+ ctime(BKE_scene_frame_get(scene))
{
BLI_spin_init(&lock);
id_hash = BLI_ghash_ptr_new("Depsgraph id hash");
@@ -140,7 +148,7 @@ static bool pointer_to_component_node_criteria(
*type = DEG_NODE_TYPE_PARAMETERS;
*subdata = "";
*operation_code = DEG_OPCODE_PARAMETERS_EVAL;
- *operation_name = pchan->name;;
+ *operation_name = pchan->name;
}
else {
/* Bone - generally, we just want the bone component. */
@@ -161,16 +169,20 @@ static bool pointer_to_component_node_criteria(
Object *object = (Object *)ptr->id.data;
bConstraint *con = (bConstraint *)ptr->data;
/* Check whether is object or bone constraint. */
+ /* NOTE: Currently none of the area can address transform of an object
+ * at a given constraint, but for rigging one might use constraint
+ * influence to be used to drive some corrective shape keys or so.
+ */
if (BLI_findindex(&object->constraints, con) != -1) {
- /* Constraint is defining object transform. */
*type = DEG_NODE_TYPE_TRANSFORM;
+ *operation_code = DEG_OPCODE_TRANSFORM_LOCAL;
return true;
}
else if (object->pose != NULL) {
- BLI_LISTBASE_FOREACH(bPoseChannel *, pchan, &object->pose->chanbase) {
+ LISTBASE_FOREACH(bPoseChannel *, pchan, &object->pose->chanbase) {
if (BLI_findindex(&pchan->constraints, con) != -1) {
- /* bone transforms */
*type = DEG_NODE_TYPE_BONE;
+ *operation_code = DEG_OPCODE_BONE_LOCAL;
*subdata = pchan->name;
return true;
}
@@ -220,12 +232,24 @@ static bool pointer_to_component_node_criteria(
*subdata = seq->name; // xxx?
return true;
}
+ else if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
+ *type = DEG_NODE_TYPE_SHADING;
+ return true;
+ }
if (prop != NULL) {
/* All unknown data effectively falls under "parameter evaluation". */
- *type = DEG_NODE_TYPE_PARAMETERS;
- *operation_code = DEG_OPCODE_PARAMETERS_EVAL;
- *operation_name = "";
- *operation_name_tag = -1;
+ if (RNA_property_is_idprop(prop)) {
+ *type = DEG_NODE_TYPE_PARAMETERS;
+ *operation_code = DEG_OPCODE_ID_PROPERTY;
+ *operation_name = RNA_property_identifier((PropertyRNA *)prop);
+ *operation_name_tag = -1;
+ }
+ else {
+ *type = DEG_NODE_TYPE_PARAMETERS;
+ *operation_code = DEG_OPCODE_PARAMETERS_EVAL;
+ *operation_name = "";
+ *operation_name_tag = -1;
+ }
return true;
}
return false;
@@ -286,7 +310,7 @@ IDDepsNode *Depsgraph::find_id_node(const ID *id) const
return reinterpret_cast<IDDepsNode *>(BLI_ghash_lookup(id_hash, id));
}
-IDDepsNode *Depsgraph::add_id_node(ID *id, bool do_tag, ID *id_cow_hint)
+IDDepsNode *Depsgraph::add_id_node(ID *id, ID *id_cow_hint)
{
BLI_assert((id->tag & LIB_TAG_COPY_ON_WRITE) == 0);
IDDepsNode *id_node = find_id_node(id);
@@ -294,9 +318,6 @@ IDDepsNode *Depsgraph::add_id_node(ID *id, bool do_tag, ID *id_cow_hint)
DepsNodeFactory *factory = deg_type_get_factory(DEG_NODE_TYPE_ID_REF);
id_node = (IDDepsNode *)factory->create_node(id, "", id->name);
id_node->init_copy_on_write(id_cow_hint);
- if (do_tag) {
- id->tag |= LIB_TAG_DOIT;
- }
/* Register node in ID hash.
*
* NOTE: We address ID nodes by the original ID pointer they are
@@ -305,9 +326,6 @@ IDDepsNode *Depsgraph::add_id_node(ID *id, bool do_tag, ID *id_cow_hint)
BLI_ghash_insert(id_hash, id, id_node);
id_nodes.push_back(id_node);
}
- else if (do_tag) {
- id->tag |= LIB_TAG_DOIT;
- }
return id_node;
}
@@ -516,15 +534,45 @@ void deg_editors_scene_update(const DEGEditorUpdateContext *update_ctx,
}
}
+bool deg_terminal_do_color(void)
+{
+ return (G.debug & G_DEBUG_DEPSGRAPH_PRETTY) != 0;
+}
+
+string deg_color_for_pointer(const void *pointer)
+{
+ if (!deg_terminal_do_color()) {
+ return "";
+ }
+ int r, g, b;
+ BLI_hash_pointer_to_color(pointer, &r, &g, &b);
+ char buffer[64];
+ BLI_snprintf(buffer, sizeof(buffer), TRUECOLOR_ANSI_COLOR_FORMAT, r, g, b);
+ return string(buffer);
+}
+
+string deg_color_end(void)
+{
+ if (!deg_terminal_do_color()) {
+ return "";
+ }
+ return string(TRUECOLOR_ANSI_COLOR_FINISH);
+}
+
} // namespace DEG
/* **************** */
/* Public Graph API */
/* Initialize a new Depsgraph */
-Depsgraph *DEG_graph_new()
+Depsgraph *DEG_graph_new(Scene *scene,
+ ViewLayer *view_layer,
+ eEvaluationMode mode)
{
- DEG::Depsgraph *deg_depsgraph = OBJECT_GUARDED_NEW(DEG::Depsgraph);
+ DEG::Depsgraph *deg_depsgraph = OBJECT_GUARDED_NEW(DEG::Depsgraph,
+ scene,
+ view_layer,
+ mode);
return reinterpret_cast<Depsgraph *>(deg_depsgraph);
}
@@ -543,3 +591,93 @@ void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func,
DEG::deg_editor_update_id_cb = id_func;
DEG::deg_editor_update_scene_cb = scene_func;
}
+
+/* Evaluation and debug */
+
+void DEG_debug_print_eval(const char *function_name,
+ const char *object_name,
+ const void *object_address)
+{
+ if ((G.debug & G_DEBUG_DEPSGRAPH_EVAL) == 0) {
+ return;
+ }
+ fprintf(stdout,
+ "%s on %s %s(%p)%s\n",
+ function_name,
+ object_name,
+ DEG::deg_color_for_pointer(object_address).c_str(),
+ object_address,
+ DEG::deg_color_end().c_str());
+ fflush(stdout);
+}
+
+void DEG_debug_print_eval_subdata(const char *function_name,
+ const char *object_name,
+ const void *object_address,
+ const char *subdata_comment,
+ const char *subdata_name,
+ const void *subdata_address)
+{
+ if ((G.debug & G_DEBUG_DEPSGRAPH_EVAL) == 0) {
+ return;
+ }
+ fprintf(stdout,
+ "%s on %s %s(%p)%s %s %s %s(%p)%s\n",
+ function_name,
+ object_name,
+ DEG::deg_color_for_pointer(object_address).c_str(),
+ object_address,
+ DEG::deg_color_end().c_str(),
+ subdata_comment,
+ subdata_name,
+ DEG::deg_color_for_pointer(subdata_address).c_str(),
+ subdata_address,
+ DEG::deg_color_end().c_str());
+ fflush(stdout);
+}
+
+void DEG_debug_print_eval_subdata_index(const char *function_name,
+ const char *object_name,
+ const void *object_address,
+ const char *subdata_comment,
+ const char *subdata_name,
+ const void *subdata_address,
+ const int subdata_index)
+{
+ if ((G.debug & G_DEBUG_DEPSGRAPH_EVAL) == 0) {
+ return;
+ }
+ fprintf(stdout,
+ "%s on %s %s(%p)^%s %s %s[%d] %s(%p)%s\n",
+ function_name,
+ object_name,
+ DEG::deg_color_for_pointer(object_address).c_str(),
+ object_address,
+ DEG::deg_color_end().c_str(),
+ subdata_comment,
+ subdata_name,
+ subdata_index,
+ DEG::deg_color_for_pointer(subdata_address).c_str(),
+ subdata_address,
+ DEG::deg_color_end().c_str());
+ fflush(stdout);
+}
+
+void DEG_debug_print_eval_time(const char *function_name,
+ const char *object_name,
+ const void *object_address,
+ float time)
+{
+ if ((G.debug & G_DEBUG_DEPSGRAPH_EVAL) == 0) {
+ return;
+ }
+ fprintf(stdout,
+ "%s on %s %s(%p)%s at time %f\n",
+ function_name,
+ object_name,
+ DEG::deg_color_for_pointer(object_address).c_str(),
+ object_address,
+ DEG::deg_color_end().c_str(),
+ time);
+ fflush(stdout);
+}
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
index f18b93c9807..9fa6b38166d 100644
--- a/source/blender/depsgraph/intern/depsgraph.h
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -38,6 +38,8 @@
#include "BLI_threads.h" /* for SpinLock */
+#include "DEG_depsgraph.h"
+
#include "intern/depsgraph_types.h"
struct ID;
@@ -100,7 +102,9 @@ struct Depsgraph {
typedef vector<OperationDepsNode *> OperationNodes;
typedef vector<IDDepsNode *> IDDepsNodes;
- Depsgraph();
+ Depsgraph(Scene *scene,
+ ViewLayer *view_layer,
+ eEvaluationMode mode);
~Depsgraph();
/**
@@ -119,7 +123,7 @@ struct Depsgraph {
TimeSourceDepsNode *find_time_source() const;
IDDepsNode *find_id_node(const ID *id) const;
- IDDepsNode *add_id_node(ID *id, bool do_tag = true, ID *id_cow_hint = NULL);
+ IDDepsNode *add_id_node(ID *id, ID *id_cow_hint = NULL);
void clear_id_nodes();
/* Add new relationship between two nodes. */
@@ -187,9 +191,13 @@ struct Depsgraph {
*/
SpinLock lock;
- /* Scene and layer this dependency graph is built for. */
+ /* Scene, layer, mode this dependency graph is built for. */
Scene *scene;
ViewLayer *view_layer;
+ eEvaluationMode mode;
+
+ /* Time at which dependency graph is being or was last evaluated. */
+ float ctime;
};
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index 902cbe039cd..c7f53b51374 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -32,22 +32,18 @@
#include "MEM_guardedalloc.h"
-// #define DEBUG_TIME
-
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
-#ifdef DEBUG_TIME
-# include "PIL_time.h"
-# include "PIL_time_utildefines.h"
-#endif
+#include "PIL_time.h"
+#include "PIL_time_utildefines.h"
extern "C" {
#include "DNA_cachefile_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "BKE_main.h"
#include "BKE_collision.h"
@@ -202,9 +198,10 @@ void DEG_graph_build_from_view_layer(Depsgraph *graph,
Scene *scene,
ViewLayer *view_layer)
{
-#ifdef DEBUG_TIME
- TIMEIT_START(DEG_graph_build_from_view_layer);
-#endif
+ double start_time;
+ if (G.debug & G_DEBUG_DEPSGRAPH_BUILD) {
+ start_time = PIL_check_seconds_timer();
+ }
DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
BLI_assert(BLI_findindex(&scene->view_layers, view_layer) != -1);
@@ -215,7 +212,7 @@ void DEG_graph_build_from_view_layer(Depsgraph *graph,
* This now could happen for both visible scene is changed and extra
* dependency graph was created for render engine.
*/
- const bool need_on_visible_update = (deg_graph->scene == NULL);
+ const bool need_on_visible_update = (deg_graph->id_nodes.size() == 0);
/* 1) Generate all the nodes in the graph first */
DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph);
@@ -257,16 +254,17 @@ void DEG_graph_build_from_view_layer(Depsgraph *graph,
}
#endif
-#ifdef DEBUG_TIME
- TIMEIT_END(DEG_graph_build_from_view_layer);
-#endif
-
/* Relations are up to date. */
deg_graph->need_update = false;
if (need_on_visible_update) {
DEG_graph_on_visible_update(bmain, graph);
}
+
+ if (G.debug & G_DEBUG_DEPSGRAPH_BUILD) {
+ printf("Depsgraph built in %f seconds.\n",
+ PIL_check_seconds_timer() - start_time);
+ }
}
/* Tag graph relations for update. */
@@ -293,9 +291,9 @@ void DEG_graph_relations_update(Depsgraph *graph,
/* Tag all relations for update. */
void DEG_relations_tag_update(Main *bmain)
{
- DEG_DEBUG_PRINTF("%s: Tagging relations for update.\n", __func__);
- BLI_LISTBASE_FOREACH (Scene *, scene, &bmain->scene) {
- BLI_LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
+ DEG_DEBUG_PRINTF(TAG, "%s: Tagging relations for update.\n", __func__);
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scene) {
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
Depsgraph *depsgraph =
(Depsgraph *)BKE_scene_get_depsgraph(scene,
view_layer,
@@ -341,45 +339,40 @@ void DEG_add_forcefield_relations(DepsNodeHandle *handle,
const char *name)
{
ListBase *effectors = pdInitEffectors(NULL, scene, object, NULL, effector_weights, false);
-
- if (effectors) {
- for (EffectorCache *eff = (EffectorCache*)effectors->first; eff; eff = eff->next) {
- if (eff->ob != object && eff->pd->forcefield != skip_forcefield) {
- DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_TRANSFORM, name);
-
- if (eff->psys) {
- DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_EVAL_PARTICLES, name);
-
- /* TODO: remove this when/if EVAL_PARTICLES is sufficient
- * for up to date particles.
- */
- DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_GEOMETRY, name);
- }
-
- if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) {
- DEG_add_object_relation(handle,
- eff->pd->f_source,
- DEG_OB_COMP_TRANSFORM,
- "Smoke Force Domain");
- DEG_add_object_relation(handle,
- eff->pd->f_source,
- DEG_OB_COMP_GEOMETRY,
- "Smoke Force Domain");
- }
-
- if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) {
- DEG_add_collision_relations(handle,
- scene,
- object,
- NULL,
- eModifierType_Collision,
- NULL,
- true,
- "Force Absorption");
- }
+ if (effectors == NULL) {
+ return;
+ }
+ for (EffectorCache *eff = (EffectorCache*)effectors->first; eff; eff = eff->next) {
+ if (eff->ob != object && eff->pd->forcefield != skip_forcefield) {
+ DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_TRANSFORM, name);
+ if (eff->psys) {
+ DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_EVAL_PARTICLES, name);
+ /* TODO: remove this when/if EVAL_PARTICLES is sufficient
+ * for up to date particles.
+ */
+ DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_GEOMETRY, name);
+ }
+ if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) {
+ DEG_add_object_relation(handle,
+ eff->pd->f_source,
+ DEG_OB_COMP_TRANSFORM,
+ "Smoke Force Domain");
+ DEG_add_object_relation(handle,
+ eff->pd->f_source,
+ DEG_OB_COMP_GEOMETRY,
+ "Smoke Force Domain");
+ }
+ if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) {
+ DEG_add_collision_relations(handle,
+ scene,
+ object,
+ NULL,
+ eModifierType_Collision,
+ NULL,
+ true,
+ "Force Absorption");
}
}
}
-
pdEndEffectors(&effectors);
}
diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc
index e8d166532ad..78b1c6f88c5 100644
--- a/source/blender/depsgraph/intern/depsgraph_debug.cc
+++ b/source/blender/depsgraph/intern/depsgraph_debug.cc
@@ -37,9 +37,12 @@ extern "C" {
#include "DNA_scene_types.h"
} /* extern "C" */
+#include "DNA_object_types.h"
+
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_debug.h"
#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#include "intern/depsgraph_intern.h"
#include "intern/nodes/deg_node_id.h"
@@ -72,7 +75,7 @@ bool DEG_debug_graph_relations_validate(Depsgraph *graph,
Scene *scene,
ViewLayer *view_layer)
{
- Depsgraph *temp_depsgraph = DEG_graph_new();
+ Depsgraph *temp_depsgraph = DEG_graph_new(scene, view_layer, DEG_get_mode(graph));
bool valid = true;
DEG_graph_build_from_view_layer(temp_depsgraph, bmain, scene, view_layer);
if (!DEG_debug_compare(temp_depsgraph, graph)) {
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc
index ad1a850a807..ac92d440bbe 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.cc
+++ b/source/blender/depsgraph/intern/depsgraph_eval.cc
@@ -32,16 +32,19 @@
#include "MEM_guardedalloc.h"
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
extern "C" {
#include "BKE_scene.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
} /* extern "C" */
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "intern/eval/deg_eval.h"
#include "intern/eval/deg_eval_flush.h"
@@ -76,19 +79,46 @@ void DEG_evaluation_context_init(EvaluationContext *eval_ctx,
eval_ctx->mode = mode;
}
-void DEG_evaluation_context_init_from_scene(EvaluationContext *eval_ctx,
- Scene *scene,
- ViewLayer *view_layer,
- RenderEngineType *engine_type,
- eEvaluationMode mode)
+void DEG_evaluation_context_init_from_scene(
+ EvaluationContext *eval_ctx,
+ Scene *scene,
+ ViewLayer *view_layer,
+ eEvaluationMode mode)
{
DEG_evaluation_context_init(eval_ctx, mode);
eval_ctx->depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
eval_ctx->view_layer = view_layer;
- eval_ctx->engine_type = engine_type;
eval_ctx->ctime = BKE_scene_frame_get(scene);
}
+void DEG_evaluation_context_init_from_view_layer_for_render(
+ EvaluationContext *eval_ctx,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ ViewLayer *view_layer)
+{
+ /* ViewLayer may come from a copy of scene.viewlayers, we need to find the original though. */
+ ViewLayer *view_layer_original = (ViewLayer *)BLI_findstring(&scene->view_layers, view_layer->name, offsetof(ViewLayer, name));
+ BLI_assert(view_layer_original != NULL);
+
+ DEG_evaluation_context_init(eval_ctx, DAG_EVAL_RENDER);
+ eval_ctx->ctime = BKE_scene_frame_get(scene);
+ eval_ctx->depsgraph = depsgraph;
+ eval_ctx->view_layer = view_layer_original;
+}
+
+void DEG_evaluation_context_init_from_depsgraph(
+ EvaluationContext *eval_ctx,
+ Depsgraph *depsgraph,
+ eEvaluationMode mode)
+{
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ DEG_evaluation_context_init(eval_ctx, mode);
+ eval_ctx->ctime = (float)scene->r.cfra + scene->r.subframe;
+ eval_ctx->depsgraph = depsgraph;
+ eval_ctx->view_layer = DEG_get_evaluated_view_layer(depsgraph);
+}
+
/* Free evaluation context. */
void DEG_evaluation_context_free(EvaluationContext *eval_ctx)
{
@@ -96,34 +126,34 @@ void DEG_evaluation_context_free(EvaluationContext *eval_ctx)
}
/* Evaluate all nodes tagged for updating. */
-void DEG_evaluate_on_refresh(EvaluationContext *eval_ctx,
- Depsgraph *graph)
+void DEG_evaluate_on_refresh(Depsgraph *graph)
{
DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ deg_graph->ctime = BKE_scene_frame_get(deg_graph->scene);
/* Update time on primary timesource. */
DEG::TimeSourceDepsNode *tsrc = deg_graph->find_time_source();
- tsrc->cfra = BKE_scene_frame_get(deg_graph->scene);
- DEG::deg_evaluate_on_refresh(eval_ctx, deg_graph);
+ tsrc->cfra = deg_graph->ctime;
+ DEG::deg_evaluate_on_refresh(deg_graph);
}
/* Frame-change happened for root scene that graph belongs to. */
-void DEG_evaluate_on_framechange(EvaluationContext *eval_ctx,
- Main *bmain,
+void DEG_evaluate_on_framechange(Main *bmain,
Depsgraph *graph,
float ctime)
{
DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ deg_graph->ctime = ctime;
/* Update time on primary timesource. */
DEG::TimeSourceDepsNode *tsrc = deg_graph->find_time_source();
tsrc->cfra = ctime;
tsrc->tag_update(deg_graph);
DEG::deg_graph_flush_updates(bmain, deg_graph);
/* Perform recalculation updates. */
- DEG::deg_evaluate_on_refresh(eval_ctx, deg_graph);
+ DEG::deg_evaluate_on_refresh(deg_graph);
}
bool DEG_needs_eval(Depsgraph *graph)
{
DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
- return BLI_gset_size(deg_graph->entry_tags) != 0;
+ return BLI_gset_len(deg_graph->entry_tags) != 0;
}
diff --git a/source/blender/depsgraph/intern/depsgraph_intern.h b/source/blender/depsgraph/intern/depsgraph_intern.h
index df5e51a3910..9961723ed17 100644
--- a/source/blender/depsgraph/intern/depsgraph_intern.h
+++ b/source/blender/depsgraph/intern/depsgraph_intern.h
@@ -112,12 +112,11 @@ void deg_editors_id_update(const DEGEditorUpdateContext *update_ctx,
void deg_editors_scene_update(const DEGEditorUpdateContext *update_ctx,
bool updated);
-#define DEG_DEBUG_PRINTF(...) \
- do { \
- if (G.debug & G_DEBUG_DEPSGRAPH) { \
- fprintf(stderr, __VA_ARGS__); \
- fflush(stderr); \
- } \
+#define DEG_DEBUG_PRINTF(type, ...) \
+ do { \
+ if (G.debug & G_DEBUG_DEPSGRAPH_ ## type) { \
+ fprintf(stderr, __VA_ARGS__); \
+ } \
} while (0)
#define DEG_ERROR_PRINTF(...) \
@@ -126,4 +125,8 @@ void deg_editors_scene_update(const DEGEditorUpdateContext *update_ctx,
fflush(stderr); \
} while (0)
+bool deg_terminal_do_color(void);
+string deg_color_for_pointer(const void *pointer);
+string deg_color_end(void);
+
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc
index 63c9aa1407a..6f0ba26c8f7 100644
--- a/source/blender/depsgraph/intern/depsgraph_query.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query.cc
@@ -45,9 +45,35 @@ extern "C" {
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
+#include "intern/eval/deg_eval_copy_on_write.h"
#include "intern/depsgraph_intern.h"
#include "intern/nodes/deg_node_id.h"
+struct Scene *DEG_get_input_scene(const Depsgraph *graph)
+{
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ return deg_graph->scene;
+}
+
+struct ViewLayer *DEG_get_input_view_layer(const Depsgraph *graph)
+{
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ return deg_graph->view_layer;
+}
+
+eEvaluationMode DEG_get_mode(const Depsgraph *graph)
+{
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ return deg_graph->mode;
+}
+
+float DEG_get_ctime(const Depsgraph *graph)
+{
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ return deg_graph->ctime;
+}
+
+
bool DEG_id_type_tagged(Main *bmain, short id_type)
{
return bmain->id_tag_update[BKE_idcode_to_index(id_type)] != 0;
@@ -77,20 +103,44 @@ short DEG_get_eval_flags_for_id(const Depsgraph *graph, ID *id)
Scene *DEG_get_evaluated_scene(const Depsgraph *graph)
{
- const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ const DEG::Depsgraph *deg_graph =
+ reinterpret_cast<const DEG::Depsgraph *>(graph);
Scene *scene_orig = deg_graph->scene;
- return reinterpret_cast<Scene *>(deg_graph->get_cow_id(&scene_orig->id));
+ Scene *scene_cow =
+ reinterpret_cast<Scene *>(deg_graph->get_cow_id(&scene_orig->id));
+ /* TODO(sergey): Shall we expand datablock here? Or is it OK to assume
+ * that calleer is OK with just a pointer in case scene is not up[dated
+ * yet?
+ */
+ return scene_cow;
}
ViewLayer *DEG_get_evaluated_view_layer(const Depsgraph *graph)
{
- const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ const DEG::Depsgraph *deg_graph =
+ reinterpret_cast<const DEG::Depsgraph *>(graph);
Scene *scene_cow = DEG_get_evaluated_scene(graph);
+ /* We update copy-on-write scene in the following cases:
+ * - It was not expanded yet.
+ * - It was tagged for update of CoW component.
+ * This allows us to have proper view layer pointer.
+ */
+ if (DEG_depsgraph_use_copy_on_write() &&
+ (!DEG::deg_copy_on_write_is_expanded(&scene_cow->id) ||
+ scene_cow->id.recalc & ID_RECALC_COPY_ON_WRITE))
+ {
+ const DEG::IDDepsNode *id_node =
+ deg_graph->find_id_node(&deg_graph->scene->id);
+ DEG::deg_update_copy_on_write_datablock(deg_graph, id_node);
+ }
+ /* Do name-based lookup. */
+ /* TODO(sergey): Can this be optimized? */
ViewLayer *view_layer_orig = deg_graph->view_layer;
ViewLayer *view_layer_cow =
(ViewLayer *)BLI_findstring(&scene_cow->view_layers,
view_layer_orig->name,
offsetof(ViewLayer, name));
+ BLI_assert(view_layer_cow != NULL);
return view_layer_cow;
}
diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
index 30c9d9f10be..61f1ccdd2a0 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
@@ -110,10 +110,18 @@ static bool deg_objects_dupli_iterator_next(BLI_Iterator *iter)
Object *dupli_parent = data->dupli_parent;
Object *temp_dupli_object = &data->temp_dupli_object;
*temp_dupli_object = *dob->ob;
- temp_dupli_object->transflag &= ~OB_DUPLI;
temp_dupli_object->select_color = dupli_parent->select_color;
temp_dupli_object->base_flag = dupli_parent->base_flag | BASE_FROMDUPLI;
+ /* Duplicated elements shouldn't care whether their original collection is visible or not. */
+ temp_dupli_object->base_flag |= BASE_VISIBLED;
+
+ if (BKE_object_is_visible(temp_dupli_object, (eObjectVisibilityCheck)data->visibility_check) == false) {
+ continue;
+ }
+
+ temp_dupli_object->transflag &= ~OB_DUPLI;
+
if (dob->collection_properties != NULL) {
temp_dupli_object->base_collection_properties = dob->collection_properties;
IDP_MergeGroup(temp_dupli_object->base_collection_properties,
@@ -181,11 +189,7 @@ static void DEG_iterator_objects_step(BLI_Iterator *iter, DEG::IDDepsNode *id_no
data->dupli_parent = object;
data->dupli_list = object_duplilist(&data->eval_ctx, data->scene, object);
data->dupli_object_next = (DupliObject *)data->dupli_list->first;
- const eObjectVisibilityCheck mode =
- (data->mode == DEG_ITER_OBJECT_MODE_RENDER)
- ? OB_VISIBILITY_CHECK_FOR_RENDER
- : OB_VISIBILITY_CHECK_FOR_VIEWPORT;
- if (BKE_object_is_visible(object, mode) == false) {
+ if (BKE_object_is_visible(object, (eObjectVisibilityCheck)data->visibility_check) == false) {
return;
}
}
@@ -210,6 +214,7 @@ void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data)
* direct dupli-objects update in group.c. Which is terribly bad, and all
* objects are expected to be evaluated already. */
DEG_evaluation_context_init(&data->eval_ctx, DAG_EVAL_VIEWPORT);
+ data->eval_ctx.depsgraph = depsgraph;
data->eval_ctx.view_layer = DEG_get_evaluated_view_layer(depsgraph);
iter->data = data;
@@ -220,6 +225,9 @@ void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data)
data->scene = DEG_get_evaluated_scene(depsgraph);
data->id_node_index = 0;
data->num_id_nodes = num_id_nodes;
+ data->visibility_check = (data->mode == DEG_ITER_OBJECT_MODE_RENDER)
+ ? OB_VISIBILITY_CHECK_FOR_RENDER
+ : OB_VISIBILITY_CHECK_FOR_VIEWPORT;
DEG::IDDepsNode *id_node = deg_graph->id_nodes[data->id_node_index];
DEG_iterator_objects_step(iter, id_node);
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index e5c714cfd74..2091d597ffa 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -40,12 +40,15 @@
#include "BLI_task.h"
extern "C" {
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
-
#include "BKE_idcode.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -92,6 +95,7 @@ void depsgraph_geometry_tag_to_component(const ID *id,
case OB_CURVE:
case OB_SURF:
case OB_FONT:
+ case OB_LATTICE:
case OB_MBALL:
case OB_GROOM:
*component_type = DEG_NODE_TYPE_GEOMETRY;
@@ -133,7 +137,7 @@ void depsgraph_select_tag_to_component_opcode(
* road.
*/
*component_type = DEG_NODE_TYPE_LAYER_COLLECTIONS;
- *operation_code = DEG_OPCODE_VIEW_LAYER_DONE;
+ *operation_code = DEG_OPCODE_VIEW_LAYER_EVAL;
}
else if (id_type == ID_OB) {
*component_type = DEG_NODE_TYPE_LAYER_COLLECTIONS;
@@ -153,7 +157,7 @@ void depsgraph_base_flags_tag_to_component_opcode(
const ID_Type id_type = GS(id->name);
if (id_type == ID_SCE) {
*component_type = DEG_NODE_TYPE_LAYER_COLLECTIONS;
- *operation_code = DEG_OPCODE_VIEW_LAYER_INIT;
+ *operation_code = DEG_OPCODE_VIEW_LAYER_EVAL;
}
else if (id_type == ID_OB) {
*component_type = DEG_NODE_TYPE_LAYER_COLLECTIONS;
@@ -196,13 +200,7 @@ void depsgraph_tag_to_component_opcode(const ID *id,
* component. Will be nice to get this unified with object,
* but we can survive for now with single exception here.
* Particles needs reconsideration anyway,
- * - We do direct injection of particle settings recalc flag
- * here. This is what we need to do for until particles
- * are switched away from own recalc flag and are using
- * ID->recalc flags instead.
*/
- ParticleSettings *particle_settings = (ParticleSettings *)id;
- particle_settings->recalc |= (tag & DEG_TAG_PSYS_ALL);
*component_type = DEG_NODE_TYPE_PARAMETERS;
}
else {
@@ -283,6 +281,13 @@ void depsgraph_tag_component(Depsgraph *graph,
operation_node->tag_update(graph);
}
}
+ /* If component depends on copy-on-write, tag it as well. */
+ if (DEG_depsgraph_use_copy_on_write() && component_node->depends_on_cow()) {
+ ComponentDepsNode *cow_comp =
+ id_node->find_component(DEG_NODE_TYPE_COPY_ON_WRITE);
+ cow_comp->tag_update(graph);
+ id_node->id_orig->recalc |= ID_RECALC_COPY_ON_WRITE;
+ }
}
/* This is a tag compatibility with legacy code.
@@ -295,11 +300,50 @@ void deg_graph_id_tag_legacy_compat(Main *bmain,
ID *id,
eDepsgraph_Tag tag)
{
- if (tag == DEG_TAG_GEOMETRY && GS(id->name) == ID_OB) {
- Object *object = (Object *)id;
- ID *data_id = (ID *)object->data;
- if (data_id != NULL) {
- DEG_id_tag_update_ex(bmain, data_id, 0);
+ if (tag == DEG_TAG_GEOMETRY || tag == 0) {
+ switch (GS(id->name)) {
+ case ID_OB:
+ {
+ Object *object = (Object *)id;
+ ID *data_id = (ID *)object->data;
+ if (data_id != NULL) {
+ DEG_id_tag_update_ex(bmain, data_id, 0);
+ }
+ break;
+ }
+ /* TODO(sergey): Shape keys are annoying, maybe we should find a
+ * way to chain geometry evaluation to them, so we don't need extra
+ * tagging here.
+ */
+ case ID_ME:
+ {
+ Mesh *mesh = (Mesh *)id;
+ ID *key_id = &mesh->key->id;
+ if (key_id != NULL) {
+ DEG_id_tag_update_ex(bmain, key_id, 0);
+ }
+ break;
+ }
+ case ID_LT:
+ {
+ Lattice *lattice = (Lattice *)id;
+ ID *key_id = &lattice->key->id;
+ if (key_id != NULL) {
+ DEG_id_tag_update_ex(bmain, key_id, 0);
+ }
+ break;
+ }
+ case ID_CU:
+ {
+ Curve *curve = (Curve *)id;
+ ID *key_id = &curve->key->id;
+ if (key_id != NULL) {
+ DEG_id_tag_update_ex(bmain, key_id, 0);
+ }
+ break;
+ }
+ default:
+ break;
}
}
}
@@ -361,11 +405,13 @@ void deg_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id, int flag)
DEG_id_type_tag(bmain, GS(id->name));
if (flag == 0) {
/* TODO(sergey): Which recalc flags to set here? */
- id->recalc |= ID_RECALC_ALL;
+ id->recalc |= ID_RECALC_ALL & ~DEG_TAG_PSYS_ALL;
if (id_node != NULL) {
id_node->tag_update(graph);
}
+ deg_graph_id_tag_legacy_compat(bmain, id, (eDepsgraph_Tag)0);
}
+ id->recalc |= flag;
int current_flag = flag;
while (current_flag != 0) {
eDepsgraph_Tag tag =
@@ -380,35 +426,16 @@ void deg_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id, int flag)
id_tag_update_ntree_special(bmain, graph, id, flag);
}
-/* TODO(sergey): Consider storing scene and view layer at depsgraph allocation
- * time.
- */
-void deg_ensure_scene_view_layer(Depsgraph *graph,
- Scene *scene,
- ViewLayer *view_layer)
-{
- if (!graph->need_update) {
- return;
- }
- graph->scene = scene;
- graph->view_layer = view_layer;
-}
-
void deg_id_tag_update(Main *bmain, ID *id, int flag)
{
deg_graph_id_tag_update(bmain, NULL, id, flag);
- BLI_LISTBASE_FOREACH (Scene *, scene, &bmain->scene) {
- BLI_LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scene) {
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
Depsgraph *depsgraph =
(Depsgraph *)BKE_scene_get_depsgraph(scene,
view_layer,
false);
if (depsgraph != NULL) {
- /* Make sure depsgraph is pointing to a correct scene and
- * view layer. This is mainly required in cases when depsgraph
- * was not built yet.
- */
- deg_ensure_scene_view_layer(depsgraph, scene, view_layer);
deg_graph_id_tag_update(bmain, depsgraph, id, flag);
}
}
@@ -438,8 +465,12 @@ void deg_graph_on_visible_update(Main *bmain, Depsgraph *graph)
scene_iter = scene_iter->set)
{
IDDepsNode *scene_id_node = graph->find_id_node(&scene_iter->id);
- BLI_assert(scene_id_node != NULL);
- scene_id_node->tag_update(graph);
+ if (scene_id_node != NULL) {
+ scene_id_node->tag_update(graph);
+ }
+ else {
+ BLI_assert(graph->need_update);
+ }
}
}
@@ -461,7 +492,9 @@ void DEG_id_tag_update_ex(Main *bmain, ID *id, int flag)
/* Ideally should not happen, but old depsgraph allowed this. */
return;
}
- DEG_DEBUG_PRINTF("%s: id=%s flag=%d\n", __func__, id->name, flag);
+ if (G.debug & G_DEBUG_DEPSGRAPH_TAG) {
+ printf("%s: id=%s flag=%d\n", __func__, id->name, flag);
+ }
DEG::deg_id_tag_update(bmain, id, flag);
}
@@ -508,8 +541,8 @@ void DEG_graph_on_visible_update(Main *bmain, Depsgraph *depsgraph)
void DEG_on_visible_update(Main *bmain, const bool UNUSED(do_time))
{
- BLI_LISTBASE_FOREACH (Scene *, scene, &bmain->scene) {
- BLI_LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scene) {
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
Depsgraph *depsgraph =
(Depsgraph *)BKE_scene_get_depsgraph(scene,
view_layer,
diff --git a/source/blender/depsgraph/intern/depsgraph_type_defines.cc b/source/blender/depsgraph/intern/depsgraph_type_defines.cc
index 22df3161428..c4fc9591611 100644
--- a/source/blender/depsgraph/intern/depsgraph_type_defines.cc
+++ b/source/blender/depsgraph/intern/depsgraph_type_defines.cc
@@ -81,6 +81,7 @@ static const char *stringify_opcode(eDepsOperation_Code opcode)
#define STRINGIFY_OPCODE(name) case DEG_OPCODE_##name: return #name
/* Generic Operations. */
STRINGIFY_OPCODE(OPERATION);
+ STRINGIFY_OPCODE(ID_PROPERTY);
STRINGIFY_OPCODE(PARAMETERS_EVAL);
STRINGIFY_OPCODE(PLACEHOLDER);
/* Animation, Drivers, etc. */
@@ -118,16 +119,15 @@ static const char *stringify_opcode(eDepsOperation_Code opcode)
STRINGIFY_OPCODE(PARTICLE_SYSTEM_EVAL_INIT);
STRINGIFY_OPCODE(PARTICLE_SYSTEM_EVAL);
STRINGIFY_OPCODE(PARTICLE_SETTINGS_EVAL);
- STRINGIFY_OPCODE(PARTICLE_SETTINGS_RECALC_CLEAR);
+ /* Point Cache. */
+ STRINGIFY_OPCODE(POINT_CACHE_RESET);
/* Batch cache. */
STRINGIFY_OPCODE(GEOMETRY_SELECT_UPDATE);
/* Masks. */
STRINGIFY_OPCODE(MASK_ANIMATION);
STRINGIFY_OPCODE(MASK_EVAL);
/* Collections. */
- STRINGIFY_OPCODE(VIEW_LAYER_INIT);
STRINGIFY_OPCODE(VIEW_LAYER_EVAL);
- STRINGIFY_OPCODE(VIEW_LAYER_DONE);
/* Copy on write. */
STRINGIFY_OPCODE(COPY_ON_WRITE);
/* Shading. */
diff --git a/source/blender/depsgraph/intern/depsgraph_types.h b/source/blender/depsgraph/intern/depsgraph_types.h
index d091f42bf80..d6c410347f6 100644
--- a/source/blender/depsgraph/intern/depsgraph_types.h
+++ b/source/blender/depsgraph/intern/depsgraph_types.h
@@ -43,6 +43,7 @@
*/
#include <string>
#include <vector>
+#include <algorithm>
struct bAction;
struct ChannelDriver;
@@ -162,6 +163,7 @@ typedef enum eDepsOperation_Code {
DEG_OPCODE_OPERATION = 0,
/* Generic parameters evaluation. */
+ DEG_OPCODE_ID_PROPERTY,
DEG_OPCODE_PARAMETERS_EVAL,
// XXX: Placeholder while porting depsgraph code
@@ -238,12 +240,12 @@ typedef enum eDepsOperation_Code {
DEG_OPCODE_PARTICLE_SYSTEM_EVAL_INIT,
DEG_OPCODE_PARTICLE_SYSTEM_EVAL,
DEG_OPCODE_PARTICLE_SETTINGS_EVAL,
- DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR,
+
+ /* Point Cache. ------------------------------------- */
+ DEG_OPCODE_POINT_CACHE_RESET,
/* Collections. ------------------------------------- */
- DEG_OPCODE_VIEW_LAYER_INIT,
DEG_OPCODE_VIEW_LAYER_EVAL,
- DEG_OPCODE_VIEW_LAYER_DONE,
/* Copy on Write. ------------------------------------ */
DEG_OPCODE_COPY_ON_WRITE,
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc
index a6c6a16a528..d40e3e85979 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval.cc
@@ -227,23 +227,25 @@ static void schedule_children(TaskPool *pool,
*
* \note Time sources should be all valid!
*/
-void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
- Depsgraph *graph)
+void deg_evaluate_on_refresh(Depsgraph *graph)
{
+ /* Set time for the current graph evaluation context. */
+ TimeSourceDepsNode *time_src = graph->find_time_source();
/* Nothing to update, early out. */
- if (BLI_gset_size(graph->entry_tags) == 0) {
+ if (BLI_gset_len(graph->entry_tags) == 0) {
return;
}
- /* Set time for the current graph evaluation context. */
- TimeSourceDepsNode *time_src = graph->find_time_source();
- eval_ctx->depsgraph = (::Depsgraph *)graph;
- eval_ctx->view_layer = DEG_get_evaluated_view_layer((::Depsgraph *)graph);
- eval_ctx->ctime = time_src->cfra;
- /* Set up evaluation context for depsgraph itself. */
+ const bool do_time_debug = ((G.debug & G_DEBUG_DEPSGRAPH_TIME) != 0);
+ const double start_time = do_time_debug ? PIL_check_seconds_timer() : 0;
+ /* Set up evaluation context. */
+ EvaluationContext eval_ctx;
+ DEG_evaluation_context_init_from_depsgraph(&eval_ctx, (::Depsgraph*)graph, graph->mode);
+ eval_ctx.ctime = time_src->cfra;
+ /* Set up evaluation state. */
DepsgraphEvalState state;
- state.eval_ctx = eval_ctx;
+ state.eval_ctx = &eval_ctx;
state.graph = graph;
- state.do_stats = (G.debug_value != 0);
+ state.do_stats = do_time_debug;
/* Set up task scheduler and pull for threaded evaluation. */
TaskScheduler *task_scheduler;
bool need_free_scheduler;
@@ -274,6 +276,10 @@ void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
if (need_free_scheduler) {
BLI_task_scheduler_free(task_scheduler);
}
+ if (do_time_debug) {
+ printf("Depsgraph updated in %f seconds.\n",
+ PIL_check_seconds_timer() - start_time);
+ }
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.h b/source/blender/depsgraph/intern/eval/deg_eval.h
index 576ab89dec1..0fb60e8f779 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.h
+++ b/source/blender/depsgraph/intern/eval/deg_eval.h
@@ -45,7 +45,6 @@ struct Depsgraph;
*
* \note Time sources should be all valid!
*/
-void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
- Depsgraph *graph);
+void deg_evaluate_on_refresh(Depsgraph *graph);
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index a6668208574..1d2169f5ec4 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -63,8 +63,10 @@ extern "C" {
#include "DNA_object_types.h"
#ifdef NESTED_ID_NASTY_WORKAROUND
+# include "DNA_curve_types.h"
# include "DNA_key_types.h"
# include "DNA_lamp_types.h"
+# include "DNA_lattice_types.h"
# include "DNA_linestyle_types.h"
# include "DNA_material_types.h"
# include "DNA_node_types.h"
@@ -85,14 +87,16 @@ extern "C" {
namespace DEG {
-#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
+#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) printf
namespace {
#ifdef NESTED_ID_NASTY_WORKAROUND
union NestedIDHackTempStorage {
+ Curve curve;
FreestyleLineStyle linestyle;
Lamp lamp;
+ Lattice lattice;
Material material;
Mesh mesh;
Scene scene;
@@ -118,6 +122,8 @@ void nested_id_hack_discard_pointers(ID *id_cow)
SPECIAL_CASE(ID_TE, Tex, nodetree)
SPECIAL_CASE(ID_WO, World, nodetree)
+ SPECIAL_CASE(ID_CU, Curve, key)
+ SPECIAL_CASE(ID_LT, Lattice, key)
SPECIAL_CASE(ID_ME, Mesh, key)
# undef SPECIAL_CASE
@@ -150,6 +156,8 @@ const ID *nested_id_hack_get_discarded_pointers(NestedIDHackTempStorage *storage
SPECIAL_CASE(ID_TE, Tex, nodetree, tex)
SPECIAL_CASE(ID_WO, World, nodetree, world)
+ SPECIAL_CASE(ID_CU, Curve, key, curve)
+ SPECIAL_CASE(ID_LT, Lattice, key, lattice)
SPECIAL_CASE(ID_ME, Mesh, key, mesh)
# undef SPECIAL_CASE
@@ -182,6 +190,8 @@ void nested_id_hack_restore_pointers(const ID *old_id, ID *new_id)
SPECIAL_CASE(ID_TE, Tex, nodetree)
SPECIAL_CASE(ID_WO, World, nodetree)
+ SPECIAL_CASE(ID_CU, Curve, key)
+ SPECIAL_CASE(ID_LT, Lattice, key)
SPECIAL_CASE(ID_ME, Mesh, key)
#undef SPECIAL_CASE
@@ -218,6 +228,8 @@ void ntree_hack_remap_pointers(const Depsgraph *depsgraph, ID *id_cow)
SPECIAL_CASE(ID_TE, Tex, nodetree, bNodeTree)
SPECIAL_CASE(ID_WO, World, nodetree, bNodeTree)
+ SPECIAL_CASE(ID_CU, Curve, key, Key)
+ SPECIAL_CASE(ID_LT, Lattice, key, Key)
SPECIAL_CASE(ID_ME, Mesh, key, Key)
#undef SPECIAL_CASE
@@ -299,17 +311,6 @@ BLI_INLINE bool check_datablock_expanded(const ID *id_cow)
return (id_cow->name[0] != '\0');
}
-/* Check whether datablock was already expanded during depsgraph
- * construction.
- */
-static bool check_datablock_expanded_at_construction(const ID *id_orig)
-{
- const ID_Type id_type = GS(id_orig->name);
- return (id_type == ID_SCE) ||
- (id_type == ID_OB && ((Object *)id_orig)->type == OB_ARMATURE) ||
- (id_type == ID_AR);
-}
-
/* Those are datablocks which are not covered by dependency graph and hence
* does not need any remapping or anything.
*
@@ -361,49 +362,50 @@ int foreach_libblock_remap_callback(void *user_data_v,
ID **id_p,
int /*cb_flag*/)
{
+ if (*id_p == NULL) {
+ return IDWALK_RET_NOP;
+ }
RemapCallbackUserData *user_data = (RemapCallbackUserData *)user_data_v;
const Depsgraph *depsgraph = user_data->depsgraph;
- if (*id_p != NULL) {
- ID *id_orig = *id_p;
- if (id_orig == user_data->temp_id) {
- DEG_COW_PRINT(" Remapping datablock for %s: id_temp=%p id_cow=%p\n",
- id_orig->name, id_orig, user_data->real_id);
- *id_p = user_data->real_id;
- }
- else if (check_datablocks_copy_on_writable(id_orig)) {
- ID *id_cow;
- if (user_data->create_placeholders) {
- /* Special workaround to stop creating temp datablocks for
- * objects which are coming from scene's collection and which
- * are never linked to any of layers.
- *
- * TODO(sergey): Ideally we need to tell ID looper to ignore
- * those or at least make it more reliable check where the
- * pointer is coming from.
- */
- const ID_Type id_type = GS(id_orig->name);
- const ID_Type id_type_self = GS(id_self->name);
- if (id_type == ID_OB && id_type_self == ID_SCE) {
- IDDepsNode *id_node = depsgraph->find_id_node(id_orig);
- if (id_node == NULL) {
- id_cow = id_orig;
- }
- else {
- id_cow = id_node->id_cow;
- }
+ ID *id_orig = *id_p;
+ if (id_orig == user_data->temp_id) {
+ DEG_COW_PRINT(" Remapping datablock for %s: id_temp=%p id_cow=%p\n",
+ id_orig->name, id_orig, user_data->real_id);
+ *id_p = user_data->real_id;
+ }
+ else if (check_datablocks_copy_on_writable(id_orig)) {
+ ID *id_cow;
+ if (user_data->create_placeholders) {
+ /* Special workaround to stop creating temp datablocks for
+ * objects which are coming from scene's collection and which
+ * are never linked to any of layers.
+ *
+ * TODO(sergey): Ideally we need to tell ID looper to ignore
+ * those or at least make it more reliable check where the
+ * pointer is coming from.
+ */
+ const ID_Type id_type = GS(id_orig->name);
+ const ID_Type id_type_self = GS(id_self->name);
+ if (id_type == ID_OB && id_type_self == ID_SCE) {
+ IDDepsNode *id_node = depsgraph->find_id_node(id_orig);
+ if (id_node == NULL) {
+ id_cow = id_orig;
}
else {
- id_cow = user_data->node_builder->ensure_cow_id(id_orig);
+ id_cow = id_node->id_cow;
}
}
else {
- id_cow = depsgraph->get_cow_id(id_orig);
+ id_cow = user_data->node_builder->ensure_cow_id(id_orig);
}
- BLI_assert(id_cow != NULL);
- DEG_COW_PRINT(" Remapping datablock for %s: id_orig=%p id_cow=%p\n",
- id_orig->name, id_orig, id_cow);
- *id_p = id_cow;
}
+ else {
+ id_cow = depsgraph->get_cow_id(id_orig);
+ }
+ BLI_assert(id_cow != NULL);
+ DEG_COW_PRINT(" Remapping datablock for %s: id_orig=%p id_cow=%p\n",
+ id_orig->name, id_orig, id_cow);
+ *id_p = id_cow;
}
return IDWALK_RET_NOP;
}
@@ -451,239 +453,9 @@ void update_special_pointers(const Depsgraph *depsgraph,
}
break;
}
- case ID_SCE:
- {
- const Scene *scene_orig = (const Scene *)id_orig;
- Scene *scene_cow = (Scene *)id_cow;
- if (scene_orig->obedit != NULL) {
- scene_cow->obedit = (Object *)depsgraph->get_cow_id(&scene_orig->obedit->id);
- }
- else {
- scene_cow->obedit = NULL;
- }
- break;
- }
- default:
- break;
- }
-}
-
-void update_copy_on_write_layer_collections(
- ListBase *layer_collections_cow,
- const ListBase *layer_collections_orig);
-
-void update_copy_on_write_layer_collection(
- LayerCollection *layer_collection_cow,
- const LayerCollection *layer_collection_orig)
-{
- // Make a local copy of original layer collection, so we can start
- // modifying it.
- LayerCollection local = *layer_collection_orig;
- // Copy all pointer data from original CoW version of layer collection.
- local.next = layer_collection_cow->next;
- local.prev = layer_collection_cow->prev;
- local.scene_collection = layer_collection_cow->scene_collection;
- local.object_bases = layer_collection_cow->object_bases;
- local.overrides = layer_collection_cow->overrides;
- local.layer_collections = layer_collection_cow->layer_collections;
- local.properties = layer_collection_cow->properties;
- local.properties_evaluated = layer_collection_cow->properties_evaluated;
- // Synchronize pointer-related data.
- IDP_Reset(local.properties, layer_collection_orig->properties);
- // Copy synchronized version back.
- *layer_collection_cow = local;
- // Recurs into nested layer collections.
- update_copy_on_write_layer_collections(
- &layer_collection_cow->layer_collections,
- &layer_collection_orig->layer_collections);
-}
-
-void update_copy_on_write_layer_collections(
- ListBase *layer_collections_cow,
- const ListBase *layer_collections_orig)
-{
- const LayerCollection *layer_collection_orig =
- (const LayerCollection *)layer_collections_orig->first;
- LayerCollection *layer_collection_cow =
- (LayerCollection *)layer_collections_cow->first;
- while (layer_collection_orig != NULL) {
- update_copy_on_write_layer_collection(layer_collection_cow,
- layer_collection_orig);
- layer_collection_orig = layer_collection_orig->next;
- layer_collection_cow = layer_collection_cow->next;
- }
-}
-
-void update_copy_on_write_view_layer(const Depsgraph *depsgraph,
- ViewLayer *view_layer_cow,
- const ViewLayer *view_layer_orig)
-{
- // Update pointers to active base.
- if (view_layer_orig->basact == NULL) {
- view_layer_cow->basact = NULL;
- }
- else {
- const Object *obact_orig = view_layer_orig->basact->object;
- Object *obact_cow = (Object *)depsgraph->get_cow_id(&obact_orig->id);
- view_layer_cow->basact = BKE_view_layer_base_find(view_layer_cow, obact_cow);
- }
- // Update base flags.
- //
- // TODO(sergey): We should probably check visibled/selectabled.
- // flag here?
- const Base *base_orig = (Base *)view_layer_orig->object_bases.first;
- Base *base_cow = (Base *)view_layer_cow->object_bases.first;;
- while (base_orig != NULL) {
- base_cow->flag = base_orig->flag;
- base_orig = base_orig->next;
- base_cow = base_cow->next;
- }
- // Synchronize settings.
- view_layer_cow->active_collection = view_layer_orig->active_collection;
- view_layer_cow->flag = view_layer_orig->flag;
- view_layer_cow->layflag = view_layer_orig->layflag;
- view_layer_cow->passflag = view_layer_orig->passflag;
- view_layer_cow->pass_alpha_threshold = view_layer_orig->pass_alpha_threshold;
- // Synchronize ID properties.
- IDP_Reset(view_layer_cow->properties, view_layer_orig->properties);
- IDP_Reset(view_layer_cow->id_properties, view_layer_orig->id_properties);
- // Synchronize layer collections.
- update_copy_on_write_layer_collections(
- &view_layer_cow->layer_collections,
- &view_layer_orig->layer_collections);
-}
-
-void update_copy_on_write_view_layers(const Depsgraph *depsgraph,
- Scene *scene_cow,
- const Scene *scene_orig)
-{
- const ViewLayer *view_layer_orig = (const ViewLayer *)scene_orig->view_layers.first;
- ViewLayer *view_layer_cow = (ViewLayer *)scene_cow->view_layers.first;
- while (view_layer_orig != NULL) {
- update_copy_on_write_view_layer(depsgraph,
- view_layer_cow,
- view_layer_orig);
- view_layer_orig = view_layer_orig->next;
- view_layer_cow = view_layer_cow->next;
- }
-}
-
-void update_copy_on_write_scene_collections(
- ListBase *collections_cow,
- const ListBase *collections_orig);
-
-void update_copy_on_write_scene_collection(
- SceneCollection *collection_cow,
- const SceneCollection *collection_orig)
-{
- collection_cow->active_object_index = collection_orig->active_object_index;
- update_copy_on_write_scene_collections(
- &collection_cow->scene_collections,
- &collection_orig->scene_collections);
-}
-
-void update_copy_on_write_scene_collections(
- ListBase *collections_cow,
- const ListBase *collections_orig)
-{
- const SceneCollection *nested_collection_orig =
- (const SceneCollection *)collections_orig->first;
- SceneCollection *nested_collection_cow =
- (SceneCollection *)collections_cow->first;
- while (nested_collection_orig != NULL) {
- update_copy_on_write_scene_collection(
- nested_collection_cow,
- nested_collection_orig);
- nested_collection_orig = nested_collection_orig->next;
- nested_collection_cow = nested_collection_cow->next;
- }
-}
-
-/* Update copy-on-write version of scene from original scene. */
-void update_copy_on_write_scene(const Depsgraph *depsgraph,
- Scene *scene_cow,
- const Scene *scene_orig)
-{
- // Some non-pointer data sync, current frame for now.
- // TODO(sergey): Are we missing something here?
- scene_cow->r.cfra = scene_orig->r.cfra;
- scene_cow->r.subframe = scene_orig->r.subframe;
- // Update view layers and collections.
- update_copy_on_write_view_layers(depsgraph, scene_cow, scene_orig);
- update_copy_on_write_scene_collection(scene_cow->collection,
- scene_orig->collection);
- // Update edit object pointer.
- if (scene_orig->obedit != NULL) {
- scene_cow->obedit = (Object *)depsgraph->get_cow_id(&scene_orig->obedit->id);
- }
- else {
- scene_cow->obedit = NULL;
- }
- /* Synchronize active render engine. */
- BLI_strncpy(scene_cow->view_render.engine_id,
- scene_orig->view_render.engine_id,
- sizeof(scene_cow->view_render.engine_id));
- /* TODO(sergey): What else do we need here? */
-}
-
-/* Update copy-on-write version of armature object from original scene. */
-void update_copy_on_write_object(const Depsgraph * /*depsgraph*/,
- Object *object_cow,
- const Object *object_orig)
-{
- /* TODO(sergey): This function might be split into a smaller ones,
- * reused for different updates. And maybe even moved to BKE.
- */
- /* Update armature/pose related flags. */
- bPose *pose_cow = object_cow->pose;
- const bPose *pose_orig = object_orig->pose;
- extract_pose_from_pose(pose_cow, pose_orig);
- /* Update object itself. */
- BKE_object_transform_copy(object_cow, object_orig);
- object_cow->mode = object_orig->mode;
-}
-
-/* Update copy-on-write version of datablock from it's original ID without re-building
- * the whole datablock from scratch.
- *
- * Used for such special cases as scene collections and armatures, which can not use full
- * re-alloc due to pointers used as function bindings.
- */
-void update_copy_on_write_datablock(const Depsgraph *depsgraph,
- const ID *id_orig, ID *id_cow)
-{
- bool ok = false;
- const ID_Type id_type = GS(id_orig->name);
- switch (id_type) {
- case ID_SCE: {
- const Scene *scene_orig = (const Scene *)id_orig;
- Scene *scene_cow = (Scene *)id_cow;
- update_copy_on_write_scene(depsgraph, scene_cow, scene_orig);
- ok = true;
- break;
- }
- case ID_OB: {
- const Object *object_orig = (const Object *)id_orig;
- Object *object_cow = (Object *)id_cow;
- if (object_orig->type == OB_ARMATURE) {
- update_copy_on_write_object(depsgraph,
- object_cow,
- object_orig);
- ok = true;
- }
- break;
- }
- case ID_AR:
- /* Nothing to do currently. */
- ok = true;
- break;
default:
break;
}
- // TODO(sergey): Other ID types here.
- if (!ok) {
- BLI_assert(!"Missing update logic of expanded datablock");
- }
}
/* This callback is used to validate that all nested ID datablocks are
@@ -716,8 +488,6 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
DepsgraphNodeBuilder *node_builder,
bool create_placeholders)
{
- BLI_assert(!create_placeholders ||
- check_datablock_expanded_at_construction(id_node->id_orig));
const ID *id_orig = id_node->id_orig;
ID *id_cow = id_node->id_cow;
/* No need to expand such datablocks, their copied ID is same as original
@@ -839,15 +609,6 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph,
if (!deg_copy_on_write_is_needed(id_orig)) {
return id_cow;
}
- /* Special case for datablocks which are expanded at the dependency graph
- * construction time. This datablocks must never change pointers of their
- * nested data since it is used for function bindings.
- */
- if (check_datablock_expanded_at_construction(id_orig)) {
- BLI_assert(check_datablock_expanded(id_cow) == true);
- update_copy_on_write_datablock(depsgraph, id_orig, id_cow);
- return id_cow;
- }
/* For the rest if datablock types we use simple logic:
* - Free previously expanded data, if any.
* - Perform full datablock copy.
@@ -878,6 +639,22 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph,
gpumaterial_ptr = &world->gpumaterial;
break;
}
+ case ID_NT:
+ {
+ /* Node trees should try to preserve their socket pointers
+ * as much as possible. This is due to UBOs code in GPU,
+ * which references sockets from trees.
+ *
+ * These flags CURRENTLY don't need full datablock update,
+ * everything is done by node tree update function which
+ * only copies socket values.
+ */
+ const int ignore_flag = (ID_RECALC_DRAW | ID_RECALC_ANIMATION);
+ if ((id_cow->recalc & ~ignore_flag) == 0) {
+ return id_cow;
+ }
+ break;
+ }
case ID_OB:
{
Object *object = (Object *)id_cow;
@@ -1009,6 +786,12 @@ void deg_evaluate_copy_on_write(const EvaluationContext * /*eval_ctx*/,
const IDDepsNode *id_node)
{
DEBUG_PRINT("%s on %s\n", __func__, id_node->id_orig->name);
+ if (id_node->id_orig == &depsgraph->scene->id) {
+ /* NOTE: This is handled by eval_ctx setup routines, which
+ * ensures scene and view layer pointers are valid.
+ */
+ return;
+ }
deg_update_copy_on_write_datablock(depsgraph, id_node);
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
index 04bfb200743..f7f55610d22 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -36,6 +36,7 @@
#include <deque>
#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
#include "BLI_task.h"
#include "BLI_ghash.h"
@@ -134,10 +135,8 @@ BLI_INLINE void flush_handle_id_node(IDDepsNode *id_node)
}
/* TODO(sergey): We can reduce number of arguments here. */
-BLI_INLINE void flush_handle_component_node(Depsgraph *graph,
- IDDepsNode *id_node,
+BLI_INLINE void flush_handle_component_node(IDDepsNode *id_node,
ComponentDepsNode *comp_node,
- bool use_copy_on_write,
FlushQueue *queue)
{
/* We only handle component once. */
@@ -145,16 +144,6 @@ BLI_INLINE void flush_handle_component_node(Depsgraph *graph,
return;
}
comp_node->done = COMPONENT_STATE_DONE;
- /* Currently this is needed to get object->mesh to be replaced with
- * original mesh (rather than being evaluated_mesh).
- *
- * TODO(sergey): This is something we need to avoid.
- */
- if (use_copy_on_write && comp_node->depends_on_cow()) {
- ComponentDepsNode *cow_comp =
- id_node->find_component(DEG_NODE_TYPE_COPY_ON_WRITE);
- cow_comp->tag_update(graph);
- }
/* Tag all required operations in component for update. */
foreach (OperationDepsNode *op, comp_node->operations) {
/* We don't want to flush tags in "upstream" direction for
@@ -167,7 +156,7 @@ BLI_INLINE void flush_handle_component_node(Depsgraph *graph,
}
op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
}
- /* When some target changes bone, we might need to re-run the
+ /* when some target changes bone, we might need to re-run the
* whole IK solver, otherwise result might be unpredictable.
*/
if (comp_node->type == DEG_NODE_TYPE_BONE) {
@@ -207,10 +196,21 @@ BLI_INLINE OperationDepsNode *flush_schedule_children(
return result;
}
+void flush_engine_data_update(ID *id)
+{
+ if (GS(id->name) != ID_OB) {
+ return;
+ }
+ Object *object = (Object *)id;
+ LISTBASE_FOREACH(ObjectEngineData *, engine_data, &object->drawdata) {
+ engine_data->recalc |= id->recalc;
+ }
+}
+
/* NOTE: It will also accumulate flags from changed components. */
-BLI_INLINE void flush_editors_id_update(Main *bmain,
- Depsgraph *graph,
- const DEGEditorUpdateContext *update_ctx)
+void flush_editors_id_update(Main *bmain,
+ Depsgraph *graph,
+ const DEGEditorUpdateContext *update_ctx)
{
foreach (IDDepsNode *id_node, graph->id_nodes) {
if (id_node->done != ID_STATE_MODIFIED) {
@@ -236,11 +236,13 @@ BLI_INLINE void flush_editors_id_update(Main *bmain,
id_cow->recalc |= factory->id_recalc_tag();
}
GHASH_FOREACH_END();
- DEG_DEBUG_PRINTF("Accumulated recalc bits for %s: %u\n",
+ DEG_DEBUG_PRINTF(EVAL, "Accumulated recalc bits for %s: %u\n",
id_orig->name, (unsigned int)id_cow->recalc);
/* Inform editors. */
if (deg_copy_on_write_is_expanded(id_cow)) {
deg_editors_id_update(update_ctx, id_cow);
+ /* Inform draw engines that something was changed. */
+ flush_engine_data_update(id_cow);
}
}
}
@@ -252,12 +254,11 @@ BLI_INLINE void flush_editors_id_update(Main *bmain,
*/
void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
{
- const bool use_copy_on_write = DEG_depsgraph_use_copy_on_write();
/* Sanity checks. */
BLI_assert(bmain != NULL);
BLI_assert(graph != NULL);
/* Nothing to update, early out. */
- if (BLI_gset_size(graph->entry_tags) == 0) {
+ if (BLI_gset_len(graph->entry_tags) == 0) {
return;
}
/* Reset all flags, get ready for the flush. */
@@ -282,10 +283,8 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
ComponentDepsNode *comp_node = op_node->owner;
IDDepsNode *id_node = comp_node->owner;
flush_handle_id_node(id_node);
- flush_handle_component_node(graph,
- id_node,
+ flush_handle_component_node(id_node,
comp_node,
- use_copy_on_write,
&queue);
/* Flush to nodes along links. */
op_node = flush_schedule_children(op_node, &queue);
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.cc b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
index 1f56edd1f87..786faa6e86c 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_component.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
@@ -301,7 +301,7 @@ OperationDepsNode *ComponentDepsNode::get_entry_operation()
if (entry_operation) {
return entry_operation;
}
- else if (operations_map != NULL && BLI_ghash_size(operations_map) == 1) {
+ else if (operations_map != NULL && BLI_ghash_len(operations_map) == 1) {
OperationDepsNode *op_node = NULL;
/* TODO(sergey): This is somewhat slow. */
GHASH_FOREACH_BEGIN(OperationDepsNode *, tmp, operations_map)
@@ -324,7 +324,7 @@ OperationDepsNode *ComponentDepsNode::get_exit_operation()
if (exit_operation) {
return exit_operation;
}
- else if (operations_map != NULL && BLI_ghash_size(operations_map) == 1) {
+ else if (operations_map != NULL && BLI_ghash_len(operations_map) == 1) {
OperationDepsNode *op_node = NULL;
/* TODO(sergey): This is somewhat slow. */
GHASH_FOREACH_BEGIN(OperationDepsNode *, tmp, operations_map)
@@ -344,7 +344,7 @@ OperationDepsNode *ComponentDepsNode::get_exit_operation()
void ComponentDepsNode::finalize_build(Depsgraph * /*graph*/)
{
- operations.reserve(BLI_ghash_size(operations_map));
+ operations.reserve(BLI_ghash_len(operations_map));
GHASH_FOREACH_BEGIN(OperationDepsNode *, op_node, operations_map)
{
operations.push_back(op_node);
@@ -381,7 +381,7 @@ DEG_COMPONENT_NODE_DEFINE(Animation, ANIMATION, ID_RECALC_ANIMA
DEG_COMPONENT_NODE_DEFINE(BatchCache, BATCH_CACHE, ID_RECALC_DRAW_CACHE);
DEG_COMPONENT_NODE_DEFINE(Bone, BONE, ID_RECALC_GEOMETRY);
DEG_COMPONENT_NODE_DEFINE(Cache, CACHE, ID_RECALC);
-DEG_COMPONENT_NODE_DEFINE(CopyOnWrite, COPY_ON_WRITE, ID_RECALC);
+DEG_COMPONENT_NODE_DEFINE(CopyOnWrite, COPY_ON_WRITE, ID_RECALC_COPY_ON_WRITE);
DEG_COMPONENT_NODE_DEFINE(Geometry, GEOMETRY, ID_RECALC_GEOMETRY);
DEG_COMPONENT_NODE_DEFINE(LayerCollections, LAYER_COLLECTIONS, ID_RECALC_COLLECTIONS);
DEG_COMPONENT_NODE_DEFINE(Parameters, PARAMETERS, ID_RECALC);
diff --git a/source/blender/depsgraph/util/deg_util_function.h b/source/blender/depsgraph/util/deg_util_function.h
index da31bb037f9..41669919c99 100644
--- a/source/blender/depsgraph/util/deg_util_function.h
+++ b/source/blender/depsgraph/util/deg_util_function.h
@@ -30,7 +30,7 @@
#pragma once
-#if (__cplusplus > 199711L)
+#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1900)
#include <functional>
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 4dcc8dc081c..1529ee7022e 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -67,7 +67,11 @@ set(SRC
intern/draw_hair.c
intern/draw_instance_data.c
intern/draw_manager.c
+ intern/draw_manager_data.c
+ intern/draw_manager_exec.c
+ intern/draw_manager_shader.c
intern/draw_manager_text.c
+ intern/draw_manager_texture.c
intern/draw_manager_profiling.c
intern/draw_view.c
modes/edit_armature_mode.c
@@ -96,8 +100,10 @@ set(SRC
engines/eevee/eevee_lightprobes.c
engines/eevee/eevee_lights.c
engines/eevee/eevee_materials.c
+ engines/eevee/eevee_mist.c
engines/eevee/eevee_motion_blur.c
engines/eevee/eevee_occlusion.c
+ engines/eevee/eevee_render.c
engines/eevee/eevee_screen_raytrace.c
engines/eevee/eevee_subsurface.c
engines/eevee/eevee_temporal_sampling.c
@@ -110,6 +116,7 @@ set(SRC
intern/draw_cache_impl.h
intern/draw_common.h
intern/draw_instance_data.h
+ intern/draw_manager.h
intern/draw_manager_text.h
intern/draw_manager_profiling.h
intern/draw_view.h
@@ -128,6 +135,9 @@ if(WITH_CLAY_ENGINE)
endif()
data_to_c_simple(engines/clay/shaders/clay_frag.glsl SRC)
+data_to_c_simple(engines/clay/shaders/clay_fxaa.glsl SRC)
+data_to_c_simple(engines/clay/shaders/clay_copy.glsl SRC)
+data_to_c_simple(engines/clay/shaders/clay_prepass_frag.glsl SRC)
data_to_c_simple(engines/clay/shaders/clay_vert.glsl SRC)
data_to_c_simple(engines/clay/shaders/clay_particle_vert.glsl SRC)
data_to_c_simple(engines/clay/shaders/clay_particle_strand_frag.glsl SRC)
@@ -165,6 +175,7 @@ data_to_c_simple(engines/eevee/shaders/effect_downsample_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_downsample_cube_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_gtao_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_minmaxz_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/effect_mist_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_motion_blur_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_ssr_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_subsurface_frag.glsl SRC)
@@ -199,7 +210,9 @@ data_to_c_simple(engines/eevee/shaders/volumetric_scatter_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/volumetric_integration_frag.glsl SRC)
data_to_c_simple(modes/shaders/common_globals_lib.glsl SRC)
+data_to_c_simple(modes/shaders/common_view_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_fxaa_lib.glsl SRC)
+data_to_c_simple(modes/shaders/common_fullscreen_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_geom_tri.glsl SRC)
@@ -228,7 +241,6 @@ data_to_c_simple(modes/shaders/object_grid_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_grid_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_lightprobe_grid_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_particle_prim_vert.glsl SRC)
-data_to_c_simple(modes/shaders/object_particle_prim_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_particle_dot_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_particle_dot_frag.glsl SRC)
data_to_c_simple(modes/shaders/paint_texture_frag.glsl SRC)
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index 0cfa1fe7d6a..cf76bfdeef5 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -26,6 +26,8 @@
#ifndef __DRW_ENGINE_H__
#define __DRW_ENGINE_H__
+#include "BLI_sys_types.h" /* for bool */
+
struct ARegion;
struct CollectionEngineSettings;
struct Depsgraph;
@@ -44,16 +46,20 @@ struct ViewContext;
struct ViewportEngineData;
struct View3D;
struct rcti;
+struct GPUMaterial;
struct GPUOffScreen;
struct GPUViewport;
+struct RenderEngine;
struct RenderEngineType;
struct WorkSpace;
-#include "BLI_sys_types.h" /* for bool */
+#include "DNA_object_enums.h"
/* Buffer and textures used by the viewport by default */
typedef struct DefaultFramebufferList {
struct GPUFrameBuffer *default_fb;
+ struct GPUFrameBuffer *color_only_fb;
+ struct GPUFrameBuffer *depth_only_fb;
struct GPUFrameBuffer *multisample_fb;
} DefaultFramebufferList;
@@ -67,6 +73,7 @@ typedef struct DefaultTextureList {
void DRW_engines_register(void);
void DRW_engines_free(void);
+bool DRW_engine_render_support(struct DrawEngineType *draw_engine_type);
void DRW_engine_register(struct DrawEngineType *draw_engine_type);
void DRW_engine_viewport_data_size_get(
const void *engine_type,
@@ -84,6 +91,11 @@ typedef struct DRWUpdateContext {
void DRW_notify_view_update(const DRWUpdateContext *update_ctx);
void DRW_notify_id_update(const DRWUpdateContext *update_ctx, struct ID *id);
+
+typedef enum eDRWSelectStage { DRW_SELECT_PASS_PRE = 1, DRW_SELECT_PASS_POST, } eDRWSelectStage;
+typedef bool (*DRW_SelectPassFn)(
+ eDRWSelectStage stage, void *user_data);
+
void DRW_draw_view(const struct bContext *C);
void DRW_draw_render_loop_ex(
@@ -104,7 +116,8 @@ void DRW_draw_render_loop_offscreen(
void DRW_draw_select_loop(
struct Depsgraph *depsgraph,
struct ARegion *ar, struct View3D *v3d,
- bool use_obedit_skip, bool use_nearest, const struct rcti *rect);
+ bool use_obedit_skip, bool use_nearest, const struct rcti *rect,
+ DRW_SelectPassFn select_pass_fn, void *select_pass_user_data);
void DRW_draw_depth_loop(
struct Depsgraph *depsgraph,
struct ARegion *ar, struct View3D *v3d);
@@ -121,4 +134,11 @@ void EDIT_ARMATURE_collection_settings_create(struct IDProperty *properties);
void PAINT_WEIGHT_collection_settings_create(struct IDProperty *properties);
void PAINT_VERTEX_collection_settings_create(struct IDProperty *properties);
+void DRW_opengl_context_create(void);
+void DRW_opengl_context_destroy(void);
+void DRW_opengl_context_enable(void);
+void DRW_opengl_context_disable(void);
+
+void DRW_deferred_shader_remove(struct GPUMaterial *mat);
+
#endif /* __DRW_ENGINE_H__ */
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c
index 10dfe7b5996..171b9111bac 100644
--- a/source/blender/draw/engines/basic/basic_engine.c
+++ b/source/blender/draw/engines/basic/basic_engine.c
@@ -46,34 +46,10 @@
/* GPUViewport.storage
* Is freed everytime the viewport engine changes */
-typedef struct BASIC_Storage {
- int dummy;
-} BASIC_Storage;
-
typedef struct BASIC_StorageList {
- struct BASIC_Storage *storage;
struct BASIC_PrivateData *g_data;
} BASIC_StorageList;
-typedef struct BASIC_FramebufferList {
- /* default */
- struct GPUFrameBuffer *default_fb;
- /* engine specific */
-#ifdef USE_DEPTH
- struct GPUFrameBuffer *dupli_depth;
-#endif
-} BASIC_FramebufferList;
-
-typedef struct BASIC_TextureList {
- /* default */
- struct GPUTexture *color;
-#ifdef USE_DEPTH
- struct GPUTexture *depth;
- /* engine specific */
- struct GPUTexture *depth_dup;
-#endif
-} BASIC_TextureList;
-
typedef struct BASIC_PassList {
#ifdef USE_DEPTH
struct DRWPass *depth_pass;
@@ -84,8 +60,8 @@ typedef struct BASIC_PassList {
typedef struct BASIC_Data {
void *engine_type;
- BASIC_FramebufferList *fbl;
- BASIC_TextureList *txl;
+ DRWViewportEmptyList *fbl;
+ DRWViewportEmptyList *txl;
BASIC_PassList *psl;
BASIC_StorageList *stl;
} BASIC_Data;
@@ -111,12 +87,8 @@ typedef struct BASIC_PrivateData {
/* Functions */
-static void basic_engine_init(void *vedata)
+static void basic_engine_init(void *UNUSED(vedata))
{
- BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
- BASIC_TextureList *txl = ((BASIC_Data *)vedata)->txl;
- BASIC_FramebufferList *fbl = ((BASIC_Data *)vedata)->fbl;
-
#ifdef USE_DEPTH
/* Depth prepass */
if (!e_data.depth_sh) {
@@ -128,20 +100,6 @@ static void basic_engine_init(void *vedata)
if (!e_data.color_sh) {
e_data.color_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
}
-
- if (!stl->storage) {
- stl->storage = MEM_callocN(sizeof(BASIC_Storage), "BASIC_Storage");
- }
-
-#ifdef USE_DEPTH
- if (DRW_state_is_fbo()) {
- const float *viewport_size = DRW_viewport_size_get();
- DRWFboTexture tex = {&txl->depth_dup, DRW_TEX_DEPTH_24_STENCIL_8, 0};
- DRW_framebuffer_init(&fbl->dupli_depth, &draw_engine_basic_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex, 1);
- }
-#endif
}
static void basic_cache_init(void *vedata)
@@ -204,8 +162,6 @@ static void basic_draw_scene(void *vedata)
{
BASIC_PassList *psl = ((BASIC_Data *)vedata)->psl;
- BASIC_FramebufferList *fbl = ((BASIC_Data *)vedata)->fbl;
- DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
const bool is_select = DRW_state_is_select();
bool use_color = true;
@@ -228,14 +184,6 @@ static void basic_draw_scene(void *vedata)
if (use_depth_cull) {
DRW_draw_pass(psl->depth_pass_cull);
}
-
- /* Pass 2 : Duplicate depth */
- if (use_depth || use_depth_cull) {
- /* Unless we go for deferred shading we need this to avoid manual depth test and artifacts */
- if (DRW_state_is_fbo()) {
- DRW_framebuffer_blit(dfbl->default_fb, fbl->dupli_depth, true, false);
- }
- }
#endif
/* Pass 3 : Shading */
@@ -264,6 +212,7 @@ DrawEngineType draw_engine_basic_type = {
&basic_draw_scene,
NULL,
NULL,
+ NULL,
};
/* Note: currently unused, we may want to register so we can see this when debugging the view. */
diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c
index a9a919f7ac2..4976cd01d11 100644
--- a/source/blender/draw/engines/clay/clay_engine.c
+++ b/source/blender/draw/engines/clay/clay_engine.c
@@ -20,7 +20,7 @@
*/
#include "BLI_utildefines.h"
-#include "BLI_dynstr.h"
+#include "BLI_string_utils.h"
#include "BLI_rand.h"
#include "DNA_particle_types.h"
@@ -51,17 +51,24 @@
#define MAX_CLAY_MAT 512 /* 512 = 9 bit material id */
-#define SHADER_DEFINES \
+#define SHADER_DEFINES_NO_AO \
"#define MAX_MATERIAL " STRINGIFY(MAX_CLAY_MAT) "\n" \
"#define USE_ROTATION\n" \
- "#define USE_AO\n" \
"#define USE_HSV\n"
+#define SHADER_DEFINES \
+ SHADER_DEFINES_NO_AO \
+ "#define USE_AO\n"
+
extern char datatoc_clay_frag_glsl[];
+extern char datatoc_clay_prepass_frag_glsl[];
+extern char datatoc_clay_copy_glsl[];
extern char datatoc_clay_vert_glsl[];
+extern char datatoc_clay_fxaa_glsl[];
extern char datatoc_clay_particle_vert_glsl[];
extern char datatoc_clay_particle_strand_frag_glsl[];
extern char datatoc_ssao_alchemy_glsl[];
+extern char datatoc_common_fxaa_lib_glsl[];
/* *********** LISTS *********** */
@@ -111,31 +118,37 @@ typedef struct CLAY_Storage {
int hair_ubo_current_id;
DRWShadingGroup *shgrps[MAX_CLAY_MAT];
DRWShadingGroup *shgrps_flat[MAX_CLAY_MAT];
+ DRWShadingGroup *shgrps_pre[MAX_CLAY_MAT];
+ DRWShadingGroup *shgrps_pre_flat[MAX_CLAY_MAT];
DRWShadingGroup *hair_shgrps[MAX_CLAY_MAT];
} CLAY_Storage;
typedef struct CLAY_StorageList {
struct CLAY_Storage *storage;
- struct GPUUniformBuffer *mat_ubo;
- struct GPUUniformBuffer *hair_mat_ubo;
struct CLAY_PrivateData *g_data;
} CLAY_StorageList;
typedef struct CLAY_FramebufferList {
- /* default */
- struct GPUFrameBuffer *default_fb;
- /* engine specific */
- struct GPUFrameBuffer *dupli_depth;
+ struct GPUFrameBuffer *antialias_fb;
+ struct GPUFrameBuffer *prepass_fb;
} CLAY_FramebufferList;
typedef struct CLAY_PassList {
- struct DRWPass *depth_pass;
- struct DRWPass *depth_pass_cull;
- struct DRWPass *clay_pass;
- struct DRWPass *clay_pass_flat;
+ struct DRWPass *clay_ps;
+ struct DRWPass *clay_cull_ps;
+ struct DRWPass *clay_flat_ps;
+ struct DRWPass *clay_flat_cull_ps;
+ struct DRWPass *clay_pre_ps;
+ struct DRWPass *clay_pre_cull_ps;
+ struct DRWPass *clay_flat_pre_ps;
+ struct DRWPass *clay_flat_pre_cull_ps;
+ struct DRWPass *clay_deferred_ps;
+ struct DRWPass *fxaa_ps;
+ struct DRWPass *copy_ps;
struct DRWPass *hair_pass;
} CLAY_PassList;
+
typedef struct CLAY_Data {
void *engine_type;
CLAY_FramebufferList *fbl;
@@ -146,6 +159,9 @@ typedef struct CLAY_Data {
typedef struct CLAY_ViewLayerData {
struct GPUTexture *jitter_tx;
+ struct GPUUniformBuffer *mat_ubo;
+ struct GPUUniformBuffer *matcaps_ubo;
+ struct GPUUniformBuffer *hair_mat_ubo;
struct GPUUniformBuffer *sampling_ubo;
int cached_sample_num;
} CLAY_ViewLayerData;
@@ -153,27 +169,22 @@ typedef struct CLAY_ViewLayerData {
/* *********** STATIC *********** */
static struct {
- /* Depth Pre Pass */
- struct GPUShader *depth_sh;
/* Shading Pass */
struct GPUShader *clay_sh;
struct GPUShader *clay_flat_sh;
+ struct GPUShader *clay_prepass_flat_sh;
+ struct GPUShader *clay_prepass_sh;
+ struct GPUShader *clay_deferred_shading_sh;
+ struct GPUShader *fxaa_sh;
+ struct GPUShader *copy_sh;
struct GPUShader *hair_sh;
-
/* Matcap textures */
struct GPUTexture *matcap_array;
- float matcap_colors[24][3];
-
- /* Ssao */
- float winmat[4][4];
- float viewvecs[3][4];
- float ssao_params[4];
-
+ float matcap_colors[24][4];
/* Just a serie of int from 0 to MAX_CLAY_MAT-1 */
int ubo_mat_idxs[MAX_CLAY_MAT];
-
- /* engine specific */
- struct GPUTexture *depth_dup;
+ /* To avoid useless texture and ubo binds. */
+ bool first_shgrp;
} e_data = {NULL}; /* Engine data */
typedef struct CLAY_PrivateData {
@@ -183,7 +194,16 @@ typedef struct CLAY_PrivateData {
DRWShadingGroup *depth_shgrp_cull;
DRWShadingGroup *depth_shgrp_cull_select;
DRWShadingGroup *depth_shgrp_cull_active;
- bool enable_ao;
+ /* Deferred shading */
+ struct GPUTexture *depth_tx; /* ref only, not alloced */
+ struct GPUTexture *normal_tx; /* ref only, not alloced */
+ struct GPUTexture *id_tx; /* ref only, not alloced */
+ struct GPUTexture *color_copy; /* ref only, not alloced */
+ bool enable_deferred_path;
+ /* Ssao */
+ float winmat[4][4];
+ float viewvecs[3][4];
+ float ssao_params[4];
} CLAY_PrivateData; /* Transient data */
/* Functions */
@@ -192,6 +212,9 @@ static void clay_view_layer_data_free(void *storage)
{
CLAY_ViewLayerData *sldata = (CLAY_ViewLayerData *)storage;
+ DRW_UBO_FREE_SAFE(sldata->mat_ubo);
+ DRW_UBO_FREE_SAFE(sldata->matcaps_ubo);
+ DRW_UBO_FREE_SAFE(sldata->hair_mat_ubo);
DRW_UBO_FREE_SAFE(sldata->sampling_ubo);
DRW_TEXTURE_FREE_SAFE(sldata->jitter_tx);
}
@@ -328,6 +351,7 @@ static void clay_engine_init(void *vedata)
CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl;
CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
/* Create Texture Array */
if (!e_data.matcap_array) {
@@ -362,49 +386,66 @@ static void clay_engine_init(void *vedata)
e_data.matcap_array = load_matcaps(prv, 24);
}
- /* Depth prepass */
- if (!e_data.depth_sh) {
- e_data.depth_sh = DRW_shader_create_3D_depth_only();
- }
-
/* Shading pass */
if (!e_data.clay_sh) {
- DynStr *ds = BLI_dynstr_new();
- char *matcap_with_ao;
-
- BLI_dynstr_append(ds, datatoc_clay_frag_glsl);
- BLI_dynstr_append(ds, datatoc_ssao_alchemy_glsl);
-
- matcap_with_ao = BLI_dynstr_get_cstring(ds);
+ char *matcap_with_ao = BLI_string_joinN(
+ datatoc_clay_frag_glsl,
+ datatoc_ssao_alchemy_glsl);
e_data.clay_sh = DRW_shader_create(
- datatoc_clay_vert_glsl, NULL, matcap_with_ao,
- SHADER_DEFINES);
+ datatoc_clay_vert_glsl, NULL, datatoc_clay_frag_glsl,
+ SHADER_DEFINES_NO_AO);
e_data.clay_flat_sh = DRW_shader_create(
- datatoc_clay_vert_glsl, NULL, matcap_with_ao,
+ datatoc_clay_vert_glsl, NULL, datatoc_clay_frag_glsl,
+ SHADER_DEFINES_NO_AO
+ "#define USE_FLAT_NORMAL\n");
+
+ e_data.clay_prepass_sh = DRW_shader_create(
+ datatoc_clay_vert_glsl, NULL, datatoc_clay_prepass_frag_glsl,
+ SHADER_DEFINES);
+ e_data.clay_prepass_flat_sh = DRW_shader_create(
+ datatoc_clay_vert_glsl, NULL, datatoc_clay_prepass_frag_glsl,
SHADER_DEFINES
"#define USE_FLAT_NORMAL\n");
- BLI_dynstr_free(ds);
+ e_data.clay_deferred_shading_sh = DRW_shader_create_fullscreen(
+ matcap_with_ao,
+ SHADER_DEFINES
+ "#define DEFERRED_SHADING\n");
+
MEM_freeN(matcap_with_ao);
- }
- if (!e_data.hair_sh) {
- e_data.hair_sh = DRW_shader_create(
- datatoc_clay_particle_vert_glsl, NULL, datatoc_clay_particle_strand_frag_glsl,
- "#define MAX_MATERIAL 512\n");
+ char *fxaa_str = BLI_string_joinN(
+ datatoc_common_fxaa_lib_glsl,
+ datatoc_clay_fxaa_glsl);
+
+ e_data.fxaa_sh = DRW_shader_create_fullscreen(fxaa_str, NULL);
+
+ MEM_freeN(fxaa_str);
+
+ e_data.copy_sh = DRW_shader_create_fullscreen(datatoc_clay_copy_glsl, NULL);
}
if (!stl->storage) {
stl->storage = MEM_callocN(sizeof(CLAY_Storage), "CLAY_Storage");
}
- if (!stl->mat_ubo) {
- stl->mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_UBO_Storage), NULL);
+ if (!stl->g_data) {
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), "CLAY_PrivateStorage");
}
- if (!stl->hair_mat_ubo) {
- stl->hair_mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_HAIR_UBO_Storage), NULL);
+ CLAY_PrivateData *g_data = stl->g_data;
+
+ if (!sldata->mat_ubo) {
+ sldata->mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_UBO_Storage), NULL);
+ }
+
+ if (!sldata->hair_mat_ubo) {
+ sldata->hair_mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_HAIR_UBO_Storage), NULL);
+ }
+
+ if (!sldata->matcaps_ubo) {
+ sldata->matcaps_ubo = DRW_uniformbuffer_create(sizeof(e_data.matcap_colors), e_data.matcap_colors);
}
if (e_data.ubo_mat_idxs[1] == 0) {
@@ -414,12 +455,29 @@ static void clay_engine_init(void *vedata)
}
}
- if (DRW_state_is_fbo()) {
+ /* FBO setup */
+ {
const float *viewport_size = DRW_viewport_size_get();
- DRWFboTexture tex = {&e_data.depth_dup, DRW_TEX_DEPTH_24_STENCIL_8, DRW_TEX_TEMP};
- DRW_framebuffer_init(&fbl->dupli_depth, &draw_engine_clay_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex, 1);
+ const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
+
+ g_data->normal_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_RG_8, &draw_engine_clay_type);
+ g_data->id_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_R_16I, &draw_engine_clay_type);
+
+ GPU_framebuffer_ensure_config(&fbl->prepass_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(g_data->normal_tx),
+ GPU_ATTACHMENT_TEXTURE(g_data->id_tx)
+ });
+
+ /* For FXAA */
+ /* TODO(fclem): OPTI: we could merge normal_tx and id_tx into a DRW_TEX_RGBA_8
+ * and reuse it for the fxaa target. */
+ g_data->color_copy = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_RGBA_8, &draw_engine_clay_type);
+
+ GPU_framebuffer_ensure_config(&fbl->antialias_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(g_data->color_copy)
+ });
}
/* SSAO setup */
@@ -445,14 +503,14 @@ static void clay_engine_init(void *vedata)
DRW_state_dfdy_factors_get(dfdyfacs);
- e_data.ssao_params[0] = ssao_samples;
- e_data.ssao_params[1] = size[0] / 64.0;
- e_data.ssao_params[2] = size[1] / 64.0;
- e_data.ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */
+ g_data->ssao_params[0] = ssao_samples;
+ g_data->ssao_params[1] = size[0] / 64.0;
+ g_data->ssao_params[2] = size[1] / 64.0;
+ g_data->ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */
/* invert the view matrix */
- DRW_viewport_matrix_get(e_data.winmat, DRW_MAT_WIN);
- invert_m4_m4(invproj, e_data.winmat);
+ DRW_viewport_matrix_get(g_data->winmat, DRW_MAT_WIN);
+ invert_m4_m4(invproj, g_data->winmat);
/* convert the view vectors to view space */
for (i = 0; i < 3; i++) {
@@ -464,19 +522,19 @@ static void clay_engine_init(void *vedata)
mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
viewvecs[i][3] = 1.0;
- copy_v4_v4(e_data.viewvecs[i], viewvecs[i]);
+ copy_v4_v4(g_data->viewvecs[i], viewvecs[i]);
}
/* we need to store the differences */
- e_data.viewvecs[1][0] -= e_data.viewvecs[0][0];
- e_data.viewvecs[1][1] = e_data.viewvecs[2][1] - e_data.viewvecs[0][1];
+ g_data->viewvecs[1][0] -= g_data->viewvecs[0][0];
+ g_data->viewvecs[1][1] = g_data->viewvecs[2][1] - g_data->viewvecs[0][1];
/* calculate a depth offset as well */
if (!is_persp) {
float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
mul_m4_v4(invproj, vec_far);
mul_v3_fl(vec_far, 1.0f / vec_far[3]);
- e_data.viewvecs[1][2] = vec_far[2] - e_data.viewvecs[0][2];
+ g_data->viewvecs[1][2] = vec_far[2] - g_data->viewvecs[0][2];
}
/* AO Samples Tex */
@@ -495,37 +553,61 @@ static void clay_engine_init(void *vedata)
}
}
-static DRWShadingGroup *CLAY_shgroup_create(CLAY_Data *vedata, DRWPass *pass, int *material_id, bool use_flat)
+static DRWShadingGroup *CLAY_shgroup_create(DRWPass *pass, GPUShader *sh, int id)
{
- CLAY_StorageList *stl = vedata->stl;
CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get();
- DRWShadingGroup *grp = DRW_shgroup_create(use_flat ? e_data.clay_flat_sh : e_data.clay_sh, pass);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_int(grp, "mat_id", &e_data.ubo_mat_idxs[id], 1);
+ if (e_data.first_shgrp) {
+ DRW_shgroup_uniform_texture_persistent(grp, "matcaps", e_data.matcap_array);
+ DRW_shgroup_uniform_block_persistent(grp, "material_block", sldata->mat_ubo);
+ DRW_shgroup_uniform_block_persistent(grp, "matcaps_block", sldata->matcaps_ubo);
+ }
+ return grp;
+}
- DRW_shgroup_uniform_vec2(grp, "screenres", DRW_viewport_size_get(), 1);
- DRW_shgroup_uniform_buffer(grp, "depthtex", &e_data.depth_dup);
- DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array);
- DRW_shgroup_uniform_mat4(grp, "WinMatrix", (float *)e_data.winmat);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)e_data.viewvecs, 3);
- DRW_shgroup_uniform_vec4(grp, "ssao_params", e_data.ssao_params, 1);
- DRW_shgroup_uniform_vec3(grp, "matcaps_color[0]", (float *)e_data.matcap_colors, 24);
+static DRWShadingGroup *CLAY_shgroup_deferred_prepass_create(DRWPass *pass, GPUShader *sh, int id)
+{
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_int(grp, "mat_id", &e_data.ubo_mat_idxs[id], 1);
- DRW_shgroup_uniform_int(grp, "mat_id", material_id, 1);
+ return grp;
+}
+static DRWShadingGroup *CLAY_shgroup_deferred_shading_create(DRWPass *pass, CLAY_PrivateData *g_data)
+{
+ CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get();
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.clay_deferred_shading_sh, pass);
+ DRW_shgroup_uniform_texture_ref(grp, "depthtex", &g_data->depth_tx);
+ DRW_shgroup_uniform_texture_ref(grp, "normaltex", &g_data->normal_tx);
+ DRW_shgroup_uniform_texture_ref(grp, "idtex", &g_data->id_tx);
+ DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array);
DRW_shgroup_uniform_texture(grp, "ssao_jitter", sldata->jitter_tx);
DRW_shgroup_uniform_block(grp, "samples_block", sldata->sampling_ubo);
- DRW_shgroup_uniform_block(grp, "material_block", stl->mat_ubo);
-
+ DRW_shgroup_uniform_block(grp, "material_block", sldata->mat_ubo);
+ DRW_shgroup_uniform_block(grp, "matcaps_block", sldata->matcaps_ubo);
+ /* TODO put in ubo */
+ DRW_shgroup_uniform_mat4(grp, "WinMatrix", (float *)g_data->winmat);
+ DRW_shgroup_uniform_vec2(grp, "invscreenres", DRW_viewport_invert_size_get(), 1);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)g_data->viewvecs, 3);
+ DRW_shgroup_uniform_vec4(grp, "ssao_params", g_data->ssao_params, 1);
return grp;
}
-static DRWShadingGroup *CLAY_hair_shgroup_create(CLAY_Data *vedata, DRWPass *pass, int *material_id)
+static DRWShadingGroup *CLAY_hair_shgroup_create(DRWPass *pass, int id)
{
- CLAY_StorageList *stl = vedata->stl;
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.hair_sh, pass);
+ CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get();
+
+ if (!e_data.hair_sh) {
+ e_data.hair_sh = DRW_shader_create(
+ datatoc_clay_particle_vert_glsl, NULL, datatoc_clay_particle_strand_frag_glsl,
+ "#define MAX_MATERIAL 512\n");
+ }
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.hair_sh, pass);
DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array);
- DRW_shgroup_uniform_int(grp, "mat_id", material_id, 1);
- DRW_shgroup_uniform_block(grp, "material_block", stl->mat_ubo);
+ DRW_shgroup_uniform_block(grp, "material_block", sldata->mat_ubo);
+ DRW_shgroup_uniform_int(grp, "mat_id", &e_data.ubo_mat_idxs[id], 1);
return grp;
}
@@ -560,25 +642,17 @@ static int search_hair_mat_to_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Mat
static int push_mat_to_ubo(CLAY_Storage *storage, const CLAY_UBO_Material *mat_ubo_test)
{
- int id = storage->ubo_current_id;
- CLAY_UBO_Material *ubo = &storage->mat_storage.materials[id];
-
- *ubo = *mat_ubo_test;
-
- storage->ubo_current_id++;
-
+ int id = storage->ubo_current_id++;
+ id = min_ii(MAX_CLAY_MAT, id);
+ storage->mat_storage.materials[id] = *mat_ubo_test;
return id;
}
static int push_hair_mat_to_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *hair_mat_ubo_test)
{
- int id = storage->hair_ubo_current_id;
- CLAY_HAIR_UBO_Material *ubo = &storage->hair_mat_storage.materials[id];
-
- *ubo = *hair_mat_ubo_test;
-
- storage->hair_ubo_current_id++;
-
+ int id = storage->hair_ubo_current_id++;
+ id = min_ii(MAX_CLAY_MAT, id);
+ storage->hair_mat_storage.materials[id] = *hair_mat_ubo_test;
return id;
}
@@ -608,11 +682,11 @@ static int hair_mat_in_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *
return id;
}
-static void ubo_mat_from_object(Object *ob, CLAY_UBO_Material *r_ubo, bool *r_needs_ao)
+static void ubo_mat_from_object(CLAY_Storage *storage, Object *ob, bool *r_needs_ao, int *r_id)
{
IDProperty *props = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_CLAY);
- /* Default Settings */
+ int matcap_icon = BKE_collection_engine_property_value_get_int(props, "matcap_icon");
float matcap_rot = BKE_collection_engine_property_value_get_float(props, "matcap_rotation");
float matcap_hue = BKE_collection_engine_property_value_get_float(props, "matcap_hue");
float matcap_sat = BKE_collection_engine_property_value_get_float(props, "matcap_saturation");
@@ -621,41 +695,45 @@ static void ubo_mat_from_object(Object *ob, CLAY_UBO_Material *r_ubo, bool *r_ne
float ssao_factor_cavity = BKE_collection_engine_property_value_get_float(props, "ssao_factor_cavity");
float ssao_factor_edge = BKE_collection_engine_property_value_get_float(props, "ssao_factor_edge");
float ssao_attenuation = BKE_collection_engine_property_value_get_float(props, "ssao_attenuation");
- int matcap_icon = BKE_collection_engine_property_value_get_int(props, "matcap_icon");
+
+ CLAY_UBO_Material r_ubo = {{0.0f}};
if (((ssao_factor_cavity > 0.0) || (ssao_factor_edge > 0.0)) &&
(ssao_distance > 0.0))
{
*r_needs_ao = true;
+
+ r_ubo.ssao_params_var[0] = ssao_distance;
+ r_ubo.ssao_params_var[1] = ssao_factor_cavity;
+ r_ubo.ssao_params_var[2] = ssao_factor_edge;
+ r_ubo.ssao_params_var[3] = ssao_attenuation;
+ }
+ else {
+ *r_needs_ao = false;
}
- memset(r_ubo, 0x0, sizeof(*r_ubo));
+ r_ubo.matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f);
+ r_ubo.matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f);
- r_ubo->matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f);
- r_ubo->matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f);
+ r_ubo.matcap_hsv[0] = matcap_hue + 0.5f;
+ r_ubo.matcap_hsv[1] = matcap_sat * 2.0f;
+ r_ubo.matcap_hsv[2] = matcap_val * 2.0f;
- r_ubo->matcap_hsv[0] = matcap_hue + 0.5f;
- r_ubo->matcap_hsv[1] = matcap_sat * 2.0f;
- r_ubo->matcap_hsv[2] = matcap_val * 2.0f;
+ r_ubo.matcap_id = matcap_to_index(matcap_icon);
- r_ubo->ssao_params_var[0] = ssao_distance;
- r_ubo->ssao_params_var[1] = ssao_factor_cavity;
- r_ubo->ssao_params_var[2] = ssao_factor_edge;
- r_ubo->ssao_params_var[3] = ssao_attenuation;
- r_ubo->matcap_id = matcap_to_index(matcap_icon);
+ *r_id = mat_in_ubo(storage, &r_ubo);
}
-static void hair_ubo_mat_from_object(Object *ob, CLAY_HAIR_UBO_Material *r_ubo)
+static void hair_ubo_mat_from_object(Object *ob, CLAY_HAIR_UBO_Material *r_ubo)
{
IDProperty *props = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_CLAY);
- /* Default Settings */
+ int matcap_icon = BKE_collection_engine_property_value_get_int(props, "matcap_icon");
float matcap_rot = BKE_collection_engine_property_value_get_float(props, "matcap_rotation");
float matcap_hue = BKE_collection_engine_property_value_get_float(props, "matcap_hue");
float matcap_sat = BKE_collection_engine_property_value_get_float(props, "matcap_saturation");
float matcap_val = BKE_collection_engine_property_value_get_float(props, "matcap_value");
float hair_randomness = BKE_collection_engine_property_value_get_float(props, "hair_brightness_randomness");
- int matcap_icon = BKE_collection_engine_property_value_get_int(props, "matcap_icon");
memset(r_ubo, 0x0, sizeof(*r_ubo));
@@ -668,25 +746,56 @@ static void hair_ubo_mat_from_object(Object *ob, CLAY_HAIR_UBO_Material *r_ubo)
r_ubo->matcap_id = matcap_to_index(matcap_icon);
}
-static DRWShadingGroup *CLAY_object_shgrp_get(
- CLAY_Data *vedata, Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl, bool use_flat)
+static DRWShadingGroup *CLAY_object_shgrp_get(CLAY_Data *vedata, Object *ob, bool use_flat, bool cull)
{
- DRWShadingGroup **shgrps = use_flat ? stl->storage->shgrps_flat : stl->storage->shgrps;
- CLAY_UBO_Material mat_ubo_test;
+ bool prepass; int id;
+ CLAY_PassList *psl = vedata->psl;
+ CLAY_Storage *storage = vedata->stl->storage;
+ DRWShadingGroup **shgrps;
+ DRWPass *pass; GPUShader *sh;
+
+ ubo_mat_from_object(storage, ob, &prepass, &id);
+
+ if (prepass) {
+ if (use_flat) {
+ shgrps = storage->shgrps_pre_flat;
+ pass = (cull) ? psl->clay_flat_pre_cull_ps : psl->clay_flat_pre_ps;
+ sh = e_data.clay_prepass_flat_sh;
+ }
+ else {
+ shgrps = storage->shgrps_pre;
+ pass = (cull) ? psl->clay_pre_cull_ps : psl->clay_pre_ps;
+ sh = e_data.clay_prepass_sh;
+ }
- ubo_mat_from_object(ob, &mat_ubo_test, &stl->g_data->enable_ao);
+ if (shgrps[id] == NULL) {
+ shgrps[id] = CLAY_shgroup_deferred_prepass_create(pass, sh, id);
+ }
- int id = mat_in_ubo(stl->storage, &mat_ubo_test);
+ vedata->stl->g_data->enable_deferred_path = true;
+ }
+ else {
+ if (use_flat) {
+ shgrps = storage->shgrps_flat;
+ pass = (cull) ? psl->clay_flat_cull_ps : psl->clay_flat_ps;
+ sh = e_data.clay_flat_sh;
+ }
+ else {
+ shgrps = storage->shgrps;
+ pass = (cull) ? psl->clay_cull_ps : psl->clay_ps;
+ sh = e_data.clay_sh;
+ }
- if (shgrps[id] == NULL) {
- shgrps[id] = CLAY_shgroup_create(
- vedata, use_flat ? psl->clay_pass_flat : psl->clay_pass, &e_data.ubo_mat_idxs[id], use_flat);
+ if (shgrps[id] == NULL) {
+ shgrps[id] = CLAY_shgroup_create(pass, sh, id);
+ e_data.first_shgrp = false;
+ }
}
return shgrps[id];
}
-static DRWShadingGroup *CLAY_hair_shgrp_get(CLAY_Data *vedata, Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl)
+static DRWShadingGroup *CLAY_hair_shgrp_get(CLAY_Data *UNUSED(vedata), Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl)
{
DRWShadingGroup **hair_shgrps = stl->storage->hair_shgrps;
@@ -696,54 +805,43 @@ static DRWShadingGroup *CLAY_hair_shgrp_get(CLAY_Data *vedata, Object *ob, CLAY_
int hair_id = hair_mat_in_ubo(stl->storage, &hair_mat_ubo_test);
if (hair_shgrps[hair_id] == NULL) {
- hair_shgrps[hair_id] = CLAY_hair_shgroup_create(vedata, psl->hair_pass, &e_data.ubo_mat_idxs[hair_id]);
+ hair_shgrps[hair_id] = CLAY_hair_shgroup_create(psl->hair_pass, hair_id);
}
return hair_shgrps[hair_id];
}
-static DRWShadingGroup *CLAY_object_shgrp_default_mode_get(
- CLAY_Data *vedata, Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl)
-{
- bool use_flat = DRW_object_is_flat_normal(ob);
- return CLAY_object_shgrp_get(vedata, ob, stl, psl, use_flat);
-}
-
static void clay_cache_init(void *vedata)
{
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
- if (!stl->g_data) {
- /* Alloc transient pointers */
- stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
- }
-
/* Disable AO unless a material needs it. */
- stl->g_data->enable_ao = false;
+ stl->g_data->enable_deferred_path = false;
- /* Depth Pass */
- {
- psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
- stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
-
- psl->depth_pass_cull = DRW_pass_create(
- "Depth Pass Cull",
- DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK);
- stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass_cull);
- }
+ /* Reset UBO datas, shgrp pointers and material id counters. */
+ memset(stl->storage, 0, sizeof(*stl->storage));
+ e_data.first_shgrp = true;
- /* Clay Pass */
+ /* Solid Passes */
{
- psl->clay_pass = DRW_pass_create("Clay Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
- stl->storage->ubo_current_id = 0;
- memset(stl->storage->shgrps, 0, sizeof(DRWShadingGroup *) * MAX_CLAY_MAT);
- }
-
- /* Clay Pass (Flat) */
- {
- psl->clay_pass_flat = DRW_pass_create("Clay Pass Flat", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
- memset(stl->storage->shgrps_flat, 0, sizeof(DRWShadingGroup *) * MAX_CLAY_MAT);
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+ psl->clay_ps = DRW_pass_create("Clay", state);
+ psl->clay_cull_ps = DRW_pass_create("Clay Culled", state | DRW_STATE_CULL_BACK);
+ psl->clay_flat_ps = DRW_pass_create("Clay Flat", state);
+ psl->clay_flat_cull_ps = DRW_pass_create("Clay Flat Culled", state | DRW_STATE_CULL_BACK);
+
+ DRWState prepass_state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+ DRWState prepass_cull_state = prepass_state | DRW_STATE_CULL_BACK;
+ psl->clay_pre_ps = DRW_pass_create("Clay Deferred Pre", prepass_state);
+ psl->clay_pre_cull_ps = DRW_pass_create("Clay Deferred Pre Culled", prepass_cull_state);
+ psl->clay_flat_pre_ps = DRW_pass_create("Clay Deferred Flat Pre", prepass_state);
+ psl->clay_flat_pre_cull_ps = DRW_pass_create("Clay Deferred Flat Pre Culled", prepass_cull_state);
+
+ psl->clay_deferred_ps = DRW_pass_create("Clay Deferred Shading", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = CLAY_shgroup_deferred_shading_create(psl->clay_deferred_ps, stl->g_data);
+ DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
/* Hair Pass */
@@ -751,8 +849,19 @@ static void clay_cache_init(void *vedata)
psl->hair_pass = DRW_pass_create(
"Hair Pass",
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_WIRE);
- stl->storage->hair_ubo_current_id = 0;
- memset(stl->storage->hair_shgrps, 0, sizeof(DRWShadingGroup *) * MAX_CLAY_MAT);
+ }
+
+ {
+ psl->fxaa_ps = DRW_pass_create("Fxaa", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.fxaa_sh, psl->fxaa_ps);
+ DRW_shgroup_uniform_texture_ref(grp, "colortex", &dtxl->color);
+ DRW_shgroup_uniform_vec2(grp, "invscreenres", DRW_viewport_invert_size_get(), 1);
+ DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+
+ psl->copy_ps = DRW_pass_create("Copy", DRW_STATE_WRITE_COLOR);
+ grp = DRW_shgroup_create(e_data.copy_sh, psl->copy_ps);
+ DRW_shgroup_uniform_texture_ref(grp, "colortex", &stl->g_data->color_copy);
+ DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
}
@@ -762,11 +871,7 @@ static void clay_cache_populate_particles(void *vedata, Object *ob)
CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
-
- Scene *scene = draw_ctx->scene;
- Object *obedit = scene->obedit;
-
- if (ob != obedit) {
+ if (ob != draw_ctx->object_edit) {
for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) {
if (psys_check_enabled(ob, psys, false)) {
ParticleSettings *part = psys->part;
@@ -791,9 +896,6 @@ static void clay_cache_populate_particles(void *vedata, Object *ob)
static void clay_cache_populate(void *vedata, Object *ob)
{
- CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
- CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
-
DRWShadingGroup *clay_shgrp;
if (!DRW_object_is_renderable(ob))
@@ -820,43 +922,27 @@ static void clay_cache_populate(void *vedata, Object *ob)
if (geom) {
IDProperty *ces_mode_ob = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_OBJECT, "");
const bool do_cull = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_backface_culling");
- const bool is_sculpt_mode = is_active && (ob->mode & OB_MODE_SCULPT) != 0;
- const bool is_default_mode_shader = is_sculpt_mode;
-
- /* Depth Prepass */
- {
- DRWShadingGroup *depth_shgrp = do_cull ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp;
- if (is_sculpt_mode) {
- DRW_shgroup_call_sculpt_add(depth_shgrp, ob, ob->obmat);
- }
- else {
- DRW_shgroup_call_object_add(depth_shgrp, geom, ob);
- }
- }
+ const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0;
+ const bool use_flat = is_sculpt_mode && DRW_object_is_flat_normal(ob);
- /* Shading */
- if (is_default_mode_shader) {
- clay_shgrp = CLAY_object_shgrp_default_mode_get(vedata, ob, stl, psl);
- }
- else {
- clay_shgrp = CLAY_object_shgrp_get(vedata, ob, stl, psl, false);
- }
+ clay_shgrp = CLAY_object_shgrp_get(vedata, ob, use_flat, do_cull);
if (is_sculpt_mode) {
DRW_shgroup_call_sculpt_add(clay_shgrp, ob, ob->obmat);
}
else {
- DRW_shgroup_call_add(clay_shgrp, geom, ob->obmat);
+ DRW_shgroup_call_object_add(clay_shgrp, geom, ob);
}
}
}
static void clay_cache_finish(void *vedata)
{
+ CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get();
CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
- DRW_uniformbuffer_update(stl->mat_ubo, &stl->storage->mat_storage);
- DRW_uniformbuffer_update(stl->hair_mat_ubo, &stl->storage->hair_mat_storage);
+ DRW_uniformbuffer_update(sldata->mat_ubo, &stl->storage->mat_storage);
+ DRW_uniformbuffer_update(sldata->hair_mat_ubo, &stl->storage->hair_mat_storage);
}
static void clay_draw_scene(void *vedata)
@@ -865,37 +951,38 @@ static void clay_draw_scene(void *vedata)
CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ stl->g_data->depth_tx = dtxl->depth;
+
+ /* Passes are ordered to have less _potential_ overdraw */
+ DRW_draw_pass(psl->clay_cull_ps);
+ DRW_draw_pass(psl->clay_flat_cull_ps);
+ DRW_draw_pass(psl->clay_ps);
+ DRW_draw_pass(psl->clay_flat_ps);
+ DRW_draw_pass(psl->hair_pass);
- /* Pass 1 : Depth pre-pass */
- if (stl->g_data->enable_ao) {
- DRW_draw_pass(psl->depth_pass);
- DRW_draw_pass(psl->depth_pass_cull);
- }
- else {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
- DRW_pass_state_set(psl->clay_pass, state);
- DRW_pass_state_set(psl->clay_pass_flat, state);
- }
+ if (stl->g_data->enable_deferred_path) {
+ GPU_framebuffer_bind(fbl->prepass_fb);
+ /* We need to clear the id texture unfortunately. */
+ const float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ GPU_framebuffer_clear_color(fbl->prepass_fb, clear_col);
- /* Pass 2 : Duplicate depth */
- /* Unless we go for deferred shading we need this to avoid manual depth test and artifacts */
- if (DRW_state_is_fbo() && stl->g_data->enable_ao) {
- /* attach temp textures */
- DRW_framebuffer_texture_attach(fbl->dupli_depth, e_data.depth_dup, 0, 0);
+ DRW_draw_pass(psl->clay_pre_cull_ps);
+ DRW_draw_pass(psl->clay_flat_pre_cull_ps);
+ DRW_draw_pass(psl->clay_pre_ps);
+ DRW_draw_pass(psl->clay_flat_pre_ps);
- DRW_framebuffer_blit(dfbl->default_fb, fbl->dupli_depth, true, false);
+ GPU_framebuffer_bind(dfbl->color_only_fb);
+ DRW_draw_pass(psl->clay_deferred_ps);
+ }
- /* detach temp textures */
- DRW_framebuffer_texture_detach(e_data.depth_dup);
+ if (true) { /* Always on for now. We might want a parameter for this. */
+ GPU_framebuffer_bind(fbl->antialias_fb);
+ DRW_draw_pass(psl->fxaa_ps);
- /* restore default fb */
- DRW_framebuffer_bind(dfbl->default_fb);
+ GPU_framebuffer_bind(dfbl->color_only_fb);
+ DRW_draw_pass(psl->copy_ps);
}
-
- /* Pass 3 : Shading */
- DRW_draw_pass(psl->clay_pass);
- DRW_draw_pass(psl->clay_pass_flat);
- DRW_draw_pass(psl->hair_pass);
}
static void clay_layer_collection_settings_create(RenderEngine *UNUSED(engine), IDProperty *props)
@@ -930,6 +1017,11 @@ static void clay_engine_free(void)
{
DRW_SHADER_FREE_SAFE(e_data.clay_sh);
DRW_SHADER_FREE_SAFE(e_data.clay_flat_sh);
+ DRW_SHADER_FREE_SAFE(e_data.clay_prepass_flat_sh);
+ DRW_SHADER_FREE_SAFE(e_data.clay_prepass_sh);
+ DRW_SHADER_FREE_SAFE(e_data.clay_deferred_shading_sh);
+ DRW_SHADER_FREE_SAFE(e_data.fxaa_sh);
+ DRW_SHADER_FREE_SAFE(e_data.copy_sh);
DRW_SHADER_FREE_SAFE(e_data.hair_sh);
DRW_TEXTURE_FREE_SAFE(e_data.matcap_array);
}
@@ -949,6 +1041,7 @@ DrawEngineType draw_engine_clay_type = {
&clay_draw_scene,
NULL,
NULL,
+ NULL,
};
RenderEngineType DRW_engine_viewport_clay_type = {
diff --git a/source/blender/draw/engines/clay/shaders/clay_copy.glsl b/source/blender/draw/engines/clay/shaders/clay_copy.glsl
new file mode 100644
index 00000000000..ec462978e67
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/clay_copy.glsl
@@ -0,0 +1,10 @@
+
+in vec4 uvcoordsvar;
+out vec4 fragColor;
+
+uniform sampler2D colortex;
+
+void main()
+{
+ fragColor = texture(colortex, uvcoordsvar.st);
+}
diff --git a/source/blender/draw/engines/clay/shaders/clay_frag.glsl b/source/blender/draw/engines/clay/shaders/clay_frag.glsl
index 9c8c90bd5b6..1939e4b735d 100644
--- a/source/blender/draw/engines/clay/shaders/clay_frag.glsl
+++ b/source/blender/draw/engines/clay/shaders/clay_frag.glsl
@@ -1,10 +1,8 @@
-uniform vec2 screenres;
-uniform sampler2D depthtex;
+uniform vec2 invscreenres;
uniform mat4 WinMatrix;
/* Matcap */
uniform sampler2DArray matcaps;
-uniform vec3 matcaps_color[24];
/* Screen Space Occlusion */
/* store the view space vectors for the corners of the view frustum here.
@@ -26,11 +24,22 @@ layout(std140) uniform samples_block {
vec4 ssao_samples[500];
};
+layout(std140) uniform matcaps_block {
+ vec4 matcaps_color[24];
+};
+
layout(std140) uniform material_block {
Material matcaps_param[MAX_MATERIAL];
};
+#ifdef DEFERRED_SHADING
+uniform sampler2D depthtex;
+uniform sampler2D normaltex;
+uniform isampler2D idtex;
+int mat_id; /* global */
+#else
uniform int mat_id;
+#endif
/* Aliases */
#define ssao_samples_num ssao_params.x
@@ -41,10 +50,12 @@ uniform int mat_id;
#define matcap_index matcaps_param[mat_id].matcap_hsv_id.w
#define matcap_rotation matcaps_param[mat_id].matcap_rot.xy
-#ifdef USE_FLAT_NORMAL
+#ifndef DEFERRED_SHADING
+# ifdef USE_FLAT_NORMAL
flat in vec3 normal;
-#else
+# else
in vec3 normal;
+# endif
#endif
out vec4 fragColor;
@@ -166,26 +177,35 @@ void ssao_factors(
out float cavities, out float edges);
#endif
-void main() {
- vec2 screenco = vec2(gl_FragCoord.xy) / screenres;
- float depth = texture(depthtex, screenco).r;
-
- vec3 position = get_view_space_from_depth(screenco, depth);
+/* From http://aras-p.info/texts/CompactNormalStorage.html
+ * Using Method #4: Spheremap Transform */
+vec3 normal_decode(vec2 enc)
+{
+ vec2 fenc = enc * 4.0 - 2.0;
+ float f = dot(fenc, fenc);
+ float g = sqrt(1.0 - f / 4.0);
+ vec3 n;
+ n.xy = fenc*g;
+ n.z = 1 - f / 2;
+ return n;
+}
+vec3 shade(vec3 N, vec3 position, float depth, vec2 screenco)
+{
#ifdef USE_ROTATION
/* Rotate texture coordinates */
vec2 rotY = vec2(-matcap_rotation.y, matcap_rotation.x);
- vec2 texco = abs(vec2(dot(normal.xy, matcap_rotation), dot(normal.xy, rotY)) * .49 + 0.5);
+ vec2 texco = abs(vec2(dot(N.xy, matcap_rotation), dot(N.xy, rotY)) * .49 + 0.5);
#else
- vec2 texco = abs(normal.xy * .49 + 0.5);
+ vec2 texco = abs(N.xy * .49 + 0.5);
#endif
vec3 col = texture(matcaps, vec3(texco, matcap_index)).rgb;
#ifdef USE_AO
- float cavity, edges;
- ssao_factors(depth, normal, position, screenco, cavity, edges);
+ float cavity = 0.0, edges = 0.0;
+ ssao_factors(depth, N, position, screenco, cavity, edges);
- col *= mix(vec3(1.0), matcaps_color[int(matcap_index)], cavity);
+ col *= mix(vec3(1.0), matcaps_color[int(matcap_index)].rgb, cavity);
#endif
#ifdef USE_HSV
@@ -197,5 +217,36 @@ void main() {
col *= edges + 1.0;
#endif
+ return col;
+}
+
+void main()
+{
+ vec2 screenco = vec2(gl_FragCoord.xy) * invscreenres;
+
+#ifdef DEFERRED_SHADING
+ ivec2 texel = ivec2(gl_FragCoord.xy);
+ mat_id = texelFetch(idtex, texel, 0).r;
+
+ /* early out (manual stencil test) */
+ if (mat_id == 0)
+ discard;
+
+ float depth = texelFetch(depthtex, texel, 0).r;
+ vec3 N = normal_decode(texelFetch(normaltex, texel, 0).rg);
+ /* see the prepass for explanations. */
+ if (mat_id < 0) {
+ N = -N;
+ }
+ mat_id = abs(mat_id) - 1;
+#else
+ float depth = gl_FragCoord.z;
+ vec3 N = normal;
+#endif
+
+ vec3 position = get_view_space_from_depth(screenco, depth);
+
+ vec3 col = shade(N, position, depth, screenco);
+
fragColor = vec4(col, 1.0);
}
diff --git a/source/blender/draw/engines/clay/shaders/clay_fxaa.glsl b/source/blender/draw/engines/clay/shaders/clay_fxaa.glsl
new file mode 100644
index 00000000000..924e51421aa
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/clay_fxaa.glsl
@@ -0,0 +1,18 @@
+
+in vec4 uvcoordsvar;
+out vec4 fragColor;
+
+uniform vec2 invscreenres;
+uniform sampler2D colortex;
+
+void main()
+{
+ fragColor = vec4(FxaaPixelShader(
+ uvcoordsvar.st,
+ colortex,
+ invscreenres,
+ 1.0,
+ 0.166,
+ 0.0833
+ ).rgb, 1.0);
+}
diff --git a/source/blender/draw/engines/clay/shaders/clay_prepass_frag.glsl b/source/blender/draw/engines/clay/shaders/clay_prepass_frag.glsl
new file mode 100644
index 00000000000..f30322bc9fe
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/clay_prepass_frag.glsl
@@ -0,0 +1,44 @@
+uniform int mat_id;
+
+#ifdef USE_FLAT_NORMAL
+flat in vec3 normal;
+#else
+in vec3 normal;
+#endif
+
+layout(location = 0) out vec2 outNormals;
+layout(location = 1) out int outIndex;
+
+/* From http://aras-p.info/texts/CompactNormalStorage.html
+ * Using Method #4: Spheremap Transform */
+vec2 normal_encode(vec3 n)
+{
+ float p = sqrt(n.z * 8.0 + 8.0);
+ return n.xy / p + 0.5;
+}
+
+/* 4x4 bayer matrix prepared for 8bit UNORM precision error. */
+#define P(x) (((x + 0.5) * (1.0 / 16.0) - 0.5) * (1.0 / 255.0))
+const vec4 dither_mat[4] = vec4[4](
+ vec4( P(0.0), P(8.0), P(2.0), P(10.0)),
+ vec4(P(12.0), P(4.0), P(14.0), P(6.0)),
+ vec4( P(3.0), P(11.0), P(1.0), P(9.0)),
+ vec4(P(15.0), P(7.0), P(13.0), P(5.0))
+);
+
+void main() {
+ outIndex = (mat_id + 1); /* 0 is clear color */
+ /**
+ * To fix the normal buffer precision issue for backfaces,
+ * we invert normals and use the sign of the index buffer
+ * to tag them, and re-invert in deferred pass.
+ **/
+ vec3 N = (gl_FrontFacing) ? normal : -normal;
+ outIndex = (gl_FrontFacing) ? outIndex : -outIndex;
+
+ outNormals = normal_encode(N);
+
+ /* Dither the output to fight low quality. */
+ ivec2 tx = ivec2(gl_FragCoord.xy) % 4;
+ outNormals += dither_mat[tx.x][tx.y];
+}
diff --git a/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl b/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl
index 48c117c3d8d..94e2d6f3c7b 100644
--- a/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl
+++ b/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl
@@ -10,6 +10,11 @@ void ssao_factors(
in float depth, in vec3 normal, in vec3 position, in vec2 screenco,
out float cavities, out float edges)
{
+ cavities = edges = 0.0;
+ /* early out if there is no need for SSAO */
+ if (ssao_factor_cavity == 0.0 && ssao_factor_edge == 0.0)
+ return;
+
/* take the normalized ray direction here */
vec3 noise = texture(ssao_jitter, screenco.xy * jitter_tilling).rgb;
@@ -22,7 +27,6 @@ void ssao_factors(
/* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */
offset *= 0.5;
- cavities = edges = 0.0;
int num_samples = int(ssao_samples_num);
/* Note. Putting noise usage here to put some ALU after texture fetch. */
diff --git a/source/blender/draw/engines/eevee/eevee_bloom.c b/source/blender/draw/engines/eevee/eevee_bloom.c
index 63c030a574f..89a7aeab4b2 100644
--- a/source/blender/draw/engines/eevee/eevee_bloom.c
+++ b/source/blender/draw/engines/eevee/eevee_bloom.c
@@ -41,7 +41,7 @@ static struct {
struct GPUShader *bloom_downsample_sh[2];
struct GPUShader *bloom_upsample_sh[2];
struct GPUShader *bloom_resolve_sh[2];
-} e_data = {NULL}; /* Engine data */
+} e_data = {{NULL}}; /* Engine data */
extern char datatoc_effect_bloom_frag_glsl[];
@@ -84,7 +84,6 @@ int EEVEE_bloom_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
- EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -112,10 +111,13 @@ int EEVEE_bloom_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
effects->blit_texel_size[0] = 1.0f / (float)blitsize[0];
effects->blit_texel_size[1] = 1.0f / (float)blitsize[1];
- DRWFboTexture tex_blit = {&txl->bloom_blit, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER};
- DRW_framebuffer_init(&fbl->bloom_blit_fb, &draw_engine_eevee_type,
- (int)blitsize[0], (int)blitsize[1],
- &tex_blit, 1);
+ effects->bloom_blit = DRW_texture_pool_query_2D(blitsize[0], blitsize[1], DRW_TEX_RGB_11_11_10,
+ &draw_engine_eevee_type);
+
+ GPU_framebuffer_ensure_config(&fbl->bloom_blit_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->bloom_blit)
+ });
/* Parameters */
float threshold = BKE_collection_engine_property_value_get_float(props, "bloom_threshold");
@@ -145,22 +147,18 @@ int EEVEE_bloom_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
for (int i = 0; i < effects->bloom_iteration_ct; ++i) {
texsize[0] /= 2; texsize[1] /= 2;
- if (GPU_type_matches(GPU_DEVICE_AMD_VEGA, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) {
- texsize[0] = MAX2(texsize[0], 17);
- texsize[1] = MAX2(texsize[1], 17);
- }
- else {
- texsize[0] = MAX2(texsize[0], 2);
- texsize[1] = MAX2(texsize[1], 2);
- }
+ texsize[0] = MAX2(texsize[0], 2);
+ texsize[1] = MAX2(texsize[1], 2);
effects->downsamp_texel_size[i][0] = 1.0f / (float)texsize[0];
effects->downsamp_texel_size[i][1] = 1.0f / (float)texsize[1];
- DRWFboTexture tex_bloom = {&txl->bloom_downsample[i], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER};
- DRW_framebuffer_init(&fbl->bloom_down_fb[i], &draw_engine_eevee_type,
- (int)texsize[0], (int)texsize[1],
- &tex_bloom, 1);
+ effects->bloom_downsample[i] = DRW_texture_pool_query_2D(texsize[0], texsize[1], DRW_TEX_RGB_11_11_10,
+ &draw_engine_eevee_type);
+ GPU_framebuffer_ensure_config(&fbl->bloom_down_fb[i], {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->bloom_downsample[i])
+ });
}
/* Upsample buffers */
@@ -168,39 +166,26 @@ int EEVEE_bloom_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
for (int i = 0; i < effects->bloom_iteration_ct - 1; ++i) {
texsize[0] /= 2; texsize[1] /= 2;
- if (GPU_type_matches(GPU_DEVICE_AMD_VEGA, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) {
- texsize[0] = MAX2(texsize[0], 17);
- texsize[1] = MAX2(texsize[1], 17);
- }
- else {
- texsize[0] = MAX2(texsize[0], 2);
- texsize[1] = MAX2(texsize[1], 2);
- }
-
- DRWFboTexture tex_bloom = {&txl->bloom_upsample[i], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER};
- DRW_framebuffer_init(&fbl->bloom_accum_fb[i], &draw_engine_eevee_type,
- (int)texsize[0], (int)texsize[1],
- &tex_bloom, 1);
+ texsize[0] = MAX2(texsize[0], 2);
+ texsize[1] = MAX2(texsize[1], 2);
+
+ effects->bloom_upsample[i] = DRW_texture_pool_query_2D(texsize[0], texsize[1], DRW_TEX_RGB_11_11_10,
+ &draw_engine_eevee_type);
+ GPU_framebuffer_ensure_config(&fbl->bloom_accum_fb[i], {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->bloom_upsample[i])
+ });
}
return EFFECT_BLOOM | EFFECT_POST_BUFFER;
}
/* Cleanup to release memory */
- DRW_TEXTURE_FREE_SAFE(txl->bloom_blit);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->bloom_blit_fb);
-
- /* Bloom and dof share this buffer. This
- * tells dof to reconfigure it's framebuffer. */
- if (txl->bloom_downsample[0] != NULL) {
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->dof_down_fb);
- }
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->bloom_blit_fb);
for (int i = 0; i < MAX_BLOOM_STEP - 1; ++i) {
- DRW_TEXTURE_FREE_SAFE(txl->bloom_downsample[i]);
- DRW_TEXTURE_FREE_SAFE(txl->bloom_upsample[i]);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->bloom_down_fb[i]);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->bloom_accum_fb[i]);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->bloom_down_fb[i]);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->bloom_accum_fb[i]);
}
return 0;
@@ -215,10 +200,10 @@ static DRWShadingGroup *eevee_create_bloom_pass(
DRWShadingGroup *grp = DRW_shgroup_create(sh, *pass);
DRW_shgroup_call_add(grp, quad, NULL);
- DRW_shgroup_uniform_buffer(grp, "sourceBuffer", &effects->unf_source_buffer);
+ DRW_shgroup_uniform_texture_ref(grp, "sourceBuffer", &effects->unf_source_buffer);
DRW_shgroup_uniform_vec2(grp, "sourceBufferTexelSize", effects->unf_source_texel_size, 1);
if (upsample) {
- DRW_shgroup_uniform_buffer(grp, "baseBuffer", &effects->unf_base_buffer);
+ DRW_shgroup_uniform_texture_ref(grp, "baseBuffer", &effects->unf_base_buffer);
DRW_shgroup_uniform_float(grp, "sampleScale", &effects->bloom_sample_scale, 1);
}
@@ -292,39 +277,39 @@ void EEVEE_bloom_draw(EEVEE_Data *vedata)
copy_v2_v2(effects->unf_source_texel_size, effects->source_texel_size);
effects->unf_source_buffer = effects->source_buffer;
- DRW_framebuffer_bind(fbl->bloom_blit_fb);
+ GPU_framebuffer_bind(fbl->bloom_blit_fb);
DRW_draw_pass(psl->bloom_blit);
/* Downsample */
copy_v2_v2(effects->unf_source_texel_size, effects->blit_texel_size);
- effects->unf_source_buffer = txl->bloom_blit;
+ effects->unf_source_buffer = effects->bloom_blit;
- DRW_framebuffer_bind(fbl->bloom_down_fb[0]);
+ GPU_framebuffer_bind(fbl->bloom_down_fb[0]);
DRW_draw_pass(psl->bloom_downsample_first);
- last = txl->bloom_downsample[0];
+ last = effects->bloom_downsample[0];
for (int i = 1; i < effects->bloom_iteration_ct; ++i) {
copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[i - 1]);
effects->unf_source_buffer = last;
- DRW_framebuffer_bind(fbl->bloom_down_fb[i]);
+ GPU_framebuffer_bind(fbl->bloom_down_fb[i]);
DRW_draw_pass(psl->bloom_downsample);
/* Used in next loop */
- last = txl->bloom_downsample[i];
+ last = effects->bloom_downsample[i];
}
/* Upsample and accumulate */
for (int i = effects->bloom_iteration_ct - 2; i >= 0; --i) {
copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[i]);
- effects->unf_source_buffer = txl->bloom_downsample[i];
+ effects->unf_source_buffer = effects->bloom_downsample[i];
effects->unf_base_buffer = last;
- DRW_framebuffer_bind(fbl->bloom_accum_fb[i]);
+ GPU_framebuffer_bind(fbl->bloom_accum_fb[i]);
DRW_draw_pass(psl->bloom_upsample);
- last = txl->bloom_upsample[i];
+ last = effects->bloom_upsample[i];
}
/* Resolve */
@@ -332,7 +317,7 @@ void EEVEE_bloom_draw(EEVEE_Data *vedata)
effects->unf_source_buffer = last;
effects->unf_base_buffer = effects->source_buffer;
- DRW_framebuffer_bind(effects->target_buffer);
+ GPU_framebuffer_bind(effects->target_buffer);
DRW_draw_pass(psl->bloom_resolve);
SWAP_BUFFERS();
}
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index 0a052b12e93..5adcf9e9ffb 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -38,8 +38,9 @@ static void eevee_view_layer_data_free(void *storage)
DRW_UBO_FREE_SAFE(sldata->light_ubo);
DRW_UBO_FREE_SAFE(sldata->shadow_ubo);
DRW_UBO_FREE_SAFE(sldata->shadow_render_ubo);
- DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_target_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_store_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cube_target_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cascade_target_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_store_fb);
DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_target);
DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_blur);
DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target);
@@ -56,8 +57,11 @@ static void eevee_view_layer_data_free(void *storage)
DRW_UBO_FREE_SAFE(sldata->grid_ubo);
DRW_UBO_FREE_SAFE(sldata->planar_ubo);
DRW_UBO_FREE_SAFE(sldata->common_ubo);
- DRW_FRAMEBUFFER_FREE_SAFE(sldata->probe_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(sldata->probe_filter_fb);
+ DRW_UBO_FREE_SAFE(sldata->clip_ubo);
+ GPU_FRAMEBUFFER_FREE_SAFE(sldata->probe_filter_fb);
+ for (int i = 0; i < 6; ++i) {
+ GPU_FRAMEBUFFER_FREE_SAFE(sldata->probe_face_fb[i]);
+ }
DRW_TEXTURE_FREE_SAFE(sldata->probe_rt);
DRW_TEXTURE_FREE_SAFE(sldata->probe_depth_rt);
DRW_TEXTURE_FREE_SAFE(sldata->probe_pool);
@@ -65,13 +69,6 @@ static void eevee_view_layer_data_free(void *storage)
DRW_TEXTURE_FREE_SAFE(sldata->irradiance_rt);
}
-static void eevee_lightprobe_data_free(void *storage)
-{
- EEVEE_LightProbeEngineData *ped = (EEVEE_LightProbeEngineData *)storage;
-
- BLI_freelistN(&ped->captured_object_list);
-}
-
EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void)
{
return (EEVEE_ViewLayerData *)DRW_view_layer_engine_data_get(
@@ -90,61 +87,95 @@ EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure(void)
return *sldata;
}
+/* Object data. */
+
+static void eevee_object_data_init(ObjectEngineData *engine_data)
+{
+ EEVEE_ObjectEngineData *eevee_data = (EEVEE_ObjectEngineData *)engine_data;
+ eevee_data->shadow_caster_id = -1;
+}
+
EEVEE_ObjectEngineData *EEVEE_object_data_get(Object *ob)
{
+ if (ELEM(ob->type, OB_LIGHTPROBE, OB_LAMP)) {
+ return NULL;
+ }
return (EEVEE_ObjectEngineData *)DRW_object_engine_data_get(
ob, &draw_engine_eevee_type);
}
EEVEE_ObjectEngineData *EEVEE_object_data_ensure(Object *ob)
{
- EEVEE_ObjectEngineData **oedata = (EEVEE_ObjectEngineData **)DRW_object_engine_data_ensure(
- ob, &draw_engine_eevee_type, NULL);
+ BLI_assert(!ELEM(ob->type, OB_LIGHTPROBE, OB_LAMP));
+ return (EEVEE_ObjectEngineData *)DRW_object_engine_data_ensure(
+ ob,
+ &draw_engine_eevee_type,
+ sizeof(EEVEE_ObjectEngineData),
+ eevee_object_data_init,
+ NULL);
+}
- if (*oedata == NULL) {
- *oedata = MEM_callocN(sizeof(**oedata), "EEVEE_ObjectEngineData");
- (*oedata)->shadow_caster_id = -1;
- }
+/* Light probe data. */
- return *oedata;
+static void eevee_lightprobe_data_init(ObjectEngineData *engine_data)
+{
+ EEVEE_LightProbeEngineData *ped = (EEVEE_LightProbeEngineData *)engine_data;
+ ped->need_full_update = true;
+ ped->need_update = true;
+}
+
+static void eevee_lightprobe_data_free(ObjectEngineData *engine_data)
+{
+ EEVEE_LightProbeEngineData *ped = (EEVEE_LightProbeEngineData *)engine_data;
+
+ BLI_freelistN(&ped->captured_object_list);
}
EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob)
{
+ if (ob->type != OB_LIGHTPROBE) {
+ return NULL;
+ }
return (EEVEE_LightProbeEngineData *)DRW_object_engine_data_get(
ob, &draw_engine_eevee_type);
}
EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_ensure(Object *ob)
{
- EEVEE_LightProbeEngineData **pedata = (EEVEE_LightProbeEngineData **)DRW_object_engine_data_ensure(
- ob, &draw_engine_eevee_type, &eevee_lightprobe_data_free);
+ BLI_assert(ob->type == OB_LIGHTPROBE);
+ return (EEVEE_LightProbeEngineData *)DRW_object_engine_data_ensure(
+ ob,
+ &draw_engine_eevee_type,
+ sizeof(EEVEE_LightProbeEngineData),
+ eevee_lightprobe_data_init,
+ eevee_lightprobe_data_free);
+}
- if (*pedata == NULL) {
- *pedata = MEM_callocN(sizeof(**pedata), "EEVEE_LightProbeEngineData");
- (*pedata)->need_full_update = true;
- (*pedata)->need_update = true;
- }
+/* Lamp data. */
- return *pedata;
+static void eevee_lamp_data_init(ObjectEngineData *engine_data)
+{
+ EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)engine_data;
+ led->need_update = true;
+ led->prev_cube_shadow_id = -1;
}
EEVEE_LampEngineData *EEVEE_lamp_data_get(Object *ob)
{
+ if (ob->type != OB_LAMP) {
+ return NULL;
+ }
return (EEVEE_LampEngineData *)DRW_object_engine_data_get(
ob, &draw_engine_eevee_type);
}
EEVEE_LampEngineData *EEVEE_lamp_data_ensure(Object *ob)
{
- EEVEE_LampEngineData **ledata = (EEVEE_LampEngineData **)DRW_object_engine_data_ensure(
- ob, &draw_engine_eevee_type, NULL);
-
- if (*ledata == NULL) {
- *ledata = MEM_callocN(sizeof(**ledata), "EEVEE_LampEngineData");
- (*ledata)->need_update = true;
- (*ledata)->prev_cube_shadow_id = -1;
- }
-
- return *ledata;
+ BLI_assert(ob->type == OB_LAMP);
+ return (EEVEE_LampEngineData *)DRW_object_engine_data_ensure(
+ ob,
+ &draw_engine_eevee_type,
+ sizeof(EEVEE_LampEngineData),
+ eevee_lamp_data_init,
+ NULL);
}
diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
index 124873add96..c7a94a877a7 100644
--- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c
+++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
@@ -32,7 +32,7 @@
#include "DNA_anim_types.h"
#include "DNA_camera_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
@@ -75,11 +75,10 @@ static void eevee_create_shader_depth_of_field(void)
datatoc_effect_dof_frag_glsl, "#define STEP_RESOLVE\n");
}
-int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, Object *camera)
{
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
- EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -88,17 +87,15 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
if (BKE_collection_engine_property_value_get_bool(props, "dof_enable")) {
Scene *scene = draw_ctx->scene;
- View3D *v3d = draw_ctx->v3d;
RegionView3D *rv3d = draw_ctx->rv3d;
if (!e_data.dof_downsample_sh) {
eevee_create_shader_depth_of_field();
}
- if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ if (camera) {
const float *viewport_size = DRW_viewport_size_get();
- Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera);
- Camera *cam = (Camera *)camera_object->data;
+ Camera *cam = (Camera *)camera->data;
/* Retreive Near and Far distance */
effects->dof_near_far[0] = -cam->clipsta;
@@ -106,39 +103,36 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
int buffer_size[2] = {(int)viewport_size[0] / 2, (int)viewport_size[1] / 2};
- /* Reuse buffer from Bloom if available */
- /* WATCH IT : must have the same size */
- struct GPUTexture **dof_down_near;
+ effects->dof_down_near = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], DRW_TEX_RGB_11_11_10,
+ &draw_engine_eevee_type);
+ effects->dof_down_far = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], DRW_TEX_RGB_11_11_10,
+ &draw_engine_eevee_type);
+ effects->dof_coc = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], DRW_TEX_RG_16,
+ &draw_engine_eevee_type);
- if ((effects->enabled_effects & EFFECT_BLOOM) != 0) {
- dof_down_near = &txl->bloom_downsample[0];
- }
- else {
- dof_down_near = &txl->dof_down_near;
- }
-
- /* Setup buffers */
- DRWFboTexture tex_down[3] = {
- {dof_down_near, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}, /* filter to not interfeer with bloom */
- {&txl->dof_down_far, DRW_TEX_RGB_11_11_10, 0},
- {&txl->dof_coc, DRW_TEX_RG_16, 0},
- };
- DRW_framebuffer_init(
- &fbl->dof_down_fb, &draw_engine_eevee_type,
- buffer_size[0], buffer_size[1], tex_down, 3);
+ GPU_framebuffer_ensure_config(&fbl->dof_down_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->dof_down_near),
+ GPU_ATTACHMENT_TEXTURE(effects->dof_down_far),
+ GPU_ATTACHMENT_TEXTURE(effects->dof_coc)
+ });
/* Go full 32bits for rendering and reduce the color artifacts. */
DRWTextureFormat fb_format = DRW_state_is_image_render() ? DRW_TEX_RGBA_32 : DRW_TEX_RGBA_16;
- DRWFboTexture tex_scatter_far = {&txl->dof_far_blur, fb_format, DRW_TEX_FILTER};
- DRW_framebuffer_init(
- &fbl->dof_scatter_far_fb, &draw_engine_eevee_type,
- buffer_size[0], buffer_size[1], &tex_scatter_far, 1);
+ effects->dof_far_blur = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], fb_format,
+ &draw_engine_eevee_type);
+ GPU_framebuffer_ensure_config(&fbl->dof_scatter_far_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->dof_far_blur),
+ });
- DRWFboTexture tex_scatter_near = {&txl->dof_near_blur, fb_format, DRW_TEX_FILTER};
- DRW_framebuffer_init(
- &fbl->dof_scatter_near_fb, &draw_engine_eevee_type,
- buffer_size[0], buffer_size[1], &tex_scatter_near, 1);
+ effects->dof_near_blur = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], fb_format,
+ &draw_engine_eevee_type);
+ GPU_framebuffer_ensure_config(&fbl->dof_scatter_near_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->dof_near_blur),
+ });
/* Parameters */
/* TODO UI Options */
@@ -147,7 +141,7 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
float rotation = cam->gpu_dof.rotation;
float ratio = 1.0f / cam->gpu_dof.ratio;
float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
- float focus_dist = BKE_camera_object_dof_distance(camera_object);
+ float focus_dist = BKE_camera_object_dof_distance(camera);
float focal_len = cam->lens;
UNUSED_VARS(rotation, ratio);
@@ -163,9 +157,13 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
float focal_len_scaled = scale_camera * focal_len;
float sensor_scaled = scale_camera * sensor;
+ if (rv3d != NULL) {
+ sensor_scaled *= rv3d->viewcamtexcofac[0];
+ }
+
effects->dof_params[0] = aperture * fabsf(focal_len_scaled / (focus_dist - focal_len_scaled));
effects->dof_params[1] = -focus_dist;
- effects->dof_params[2] = viewport_size[0] / (rv3d->viewcamtexcofac[0] * sensor_scaled);
+ effects->dof_params[2] = viewport_size[0] / sensor_scaled;
effects->dof_bokeh[0] = blades;
effects->dof_bokeh[1] = rotation;
effects->dof_bokeh[2] = ratio;
@@ -176,14 +174,9 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
}
/* Cleanup to release memory */
- DRW_TEXTURE_FREE_SAFE(txl->dof_down_near);
- DRW_TEXTURE_FREE_SAFE(txl->dof_down_far);
- DRW_TEXTURE_FREE_SAFE(txl->dof_coc);
- DRW_TEXTURE_FREE_SAFE(txl->dof_far_blur);
- DRW_TEXTURE_FREE_SAFE(txl->dof_near_blur);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->dof_down_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->dof_scatter_far_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->dof_scatter_near_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->dof_down_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->dof_scatter_far_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->dof_scatter_near_fb);
return 0;
}
@@ -192,7 +185,6 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
- EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
@@ -212,8 +204,8 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_
psl->dof_down = DRW_pass_create("DoF Downsample", DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(e_data.dof_downsample_sh, psl->dof_down);
- DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->source_buffer);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_vec2(grp, "nearFar", effects->dof_near_far, 1);
DRW_shgroup_uniform_vec3(grp, "dofParams", effects->dof_params, 1);
DRW_shgroup_call_add(grp, quad, NULL);
@@ -226,18 +218,18 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_
const int sprite_ct = ((int)viewport_size[0] / 2) * ((int)viewport_size[1] / 2); /* brackets matters */
grp = DRW_shgroup_empty_tri_batch_create(e_data.dof_scatter_sh, psl->dof_scatter, sprite_ct);
- DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->unf_source_buffer);
- DRW_shgroup_uniform_buffer(grp, "cocBuffer", &txl->dof_coc);
+ DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->unf_source_buffer);
+ DRW_shgroup_uniform_texture_ref(grp, "cocBuffer", &effects->dof_coc);
DRW_shgroup_uniform_vec2(grp, "layerSelection", effects->dof_layer_select, 1);
DRW_shgroup_uniform_vec4(grp, "bokehParams", effects->dof_bokeh, 1);
psl->dof_resolve = DRW_pass_create("DoF Resolve", DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(e_data.dof_resolve_sh, psl->dof_resolve);
- DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->source_buffer);
- DRW_shgroup_uniform_buffer(grp, "nearBuffer", &txl->dof_near_blur);
- DRW_shgroup_uniform_buffer(grp, "farBuffer", &txl->dof_far_blur);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer);
+ DRW_shgroup_uniform_texture_ref(grp, "nearBuffer", &effects->dof_near_blur);
+ DRW_shgroup_uniform_texture_ref(grp, "farBuffer", &effects->dof_far_blur);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_vec2(grp, "nearFar", effects->dof_near_far, 1);
DRW_shgroup_uniform_vec3(grp, "dofParams", effects->dof_params, 1);
DRW_shgroup_call_add(grp, quad, NULL);
@@ -257,31 +249,25 @@ void EEVEE_depth_of_field_draw(EEVEE_Data *vedata)
float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
/* Downsample */
- DRW_framebuffer_bind(fbl->dof_down_fb);
+ GPU_framebuffer_bind(fbl->dof_down_fb);
DRW_draw_pass(psl->dof_down);
/* Scatter Far */
- effects->unf_source_buffer = txl->dof_down_far;
+ effects->unf_source_buffer = effects->dof_down_far;
copy_v2_fl2(effects->dof_layer_select, 0.0f, 1.0f);
- DRW_framebuffer_bind(fbl->dof_scatter_far_fb);
- DRW_framebuffer_clear(true, false, false, clear_col, 0.0f);
+ GPU_framebuffer_bind(fbl->dof_scatter_far_fb);
+ GPU_framebuffer_clear_color(fbl->dof_scatter_far_fb, clear_col);
DRW_draw_pass(psl->dof_scatter);
/* Scatter Near */
- if ((effects->enabled_effects & EFFECT_BLOOM) != 0) {
- /* Reuse bloom half res buffer */
- effects->unf_source_buffer = txl->bloom_downsample[0];
- }
- else {
- effects->unf_source_buffer = txl->dof_down_near;
- }
+ effects->unf_source_buffer = effects->dof_down_near;
copy_v2_fl2(effects->dof_layer_select, 1.0f, 0.0f);
- DRW_framebuffer_bind(fbl->dof_scatter_near_fb);
- DRW_framebuffer_clear(true, false, false, clear_col, 0.0f);
+ GPU_framebuffer_bind(fbl->dof_scatter_near_fb);
+ GPU_framebuffer_clear_color(fbl->dof_scatter_near_fb, clear_col);
DRW_draw_pass(psl->dof_scatter);
/* Resolve */
- DRW_framebuffer_bind(effects->target_buffer);
+ GPU_framebuffer_bind(effects->target_buffer);
DRW_draw_pass(psl->dof_resolve);
SWAP_BUFFERS();
}
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 5821111c59d..977eb14a1bb 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -27,8 +27,6 @@
#include "DRW_render.h"
-#include "BKE_global.h" /* for G.debug_value */
-
#include "eevee_private.h"
#include "GPU_texture.h"
#include "GPU_extensions.h"
@@ -100,16 +98,18 @@ static void eevee_create_shader_downsample(void)
"#define COPY_DEPTH\n");
}
-void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera)
{
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
const float *viewport_size = DRW_viewport_size_get();
-
/* Shaders */
if (!e_data.downsample_sh) {
eevee_create_shader_downsample();
@@ -122,44 +122,62 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
effects = stl->effects;
effects->enabled_effects = 0;
- effects->enabled_effects |= EEVEE_motion_blur_init(sldata, vedata);
+ effects->enabled_effects |= EEVEE_motion_blur_init(sldata, vedata, camera);
effects->enabled_effects |= EEVEE_bloom_init(sldata, vedata);
- effects->enabled_effects |= EEVEE_depth_of_field_init(sldata, vedata);
+ effects->enabled_effects |= EEVEE_depth_of_field_init(sldata, vedata, camera);
effects->enabled_effects |= EEVEE_temporal_sampling_init(sldata, vedata);
effects->enabled_effects |= EEVEE_occlusion_init(sldata, vedata);
effects->enabled_effects |= EEVEE_subsurface_init(sldata, vedata);
effects->enabled_effects |= EEVEE_screen_raytrace_init(sldata, vedata);
effects->enabled_effects |= EEVEE_volumes_init(sldata, vedata);
+ /* Force normal buffer creation. */
+ if (DRW_state_is_image_render() &&
+ (view_layer->passflag & SCE_PASS_NORMAL) != 0)
+ {
+ effects->enabled_effects |= EFFECT_NORMAL_BUFFER;
+ }
+
/**
* Ping Pong buffer
*/
if ((effects->enabled_effects & EFFECT_POST_BUFFER) != 0) {
- DRWFboTexture tex = {&txl->color_post, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
- DRW_framebuffer_init(&fbl->effect_fb, &draw_engine_eevee_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex, 1);
+ DRW_texture_ensure_fullscreen_2D(&txl->color_post, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP);
+
+ GPU_framebuffer_ensure_config(&fbl->effect_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(txl->color_post),
+ });
+
+ GPU_framebuffer_ensure_config(&fbl->effect_color_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->color_post),
+ });
}
else {
/* Cleanup to release memory */
DRW_TEXTURE_FREE_SAFE(txl->color_post);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->effect_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->effect_fb);
}
/**
* MinMax Pyramid
*/
- DRWFboTexture texmax = {&txl->maxzbuffer, DRW_TEX_DEPTH_24, DRW_TEX_MIPMAP};
+ int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
+ size[0] = max_ii(size[0] / 2, 1);
+ size[1] = max_ii(size[1] / 2, 1);
if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
/* Intel gpu seems to have problem rendering to only depth format */
- texmax.format = DRW_TEX_R_32;
+ DRW_texture_ensure_2D(&txl->maxzbuffer, size[0], size[1], DRW_TEX_R_32, DRW_TEX_MIPMAP);
+ }
+ else {
+ DRW_texture_ensure_2D(&txl->maxzbuffer, size[0], size[1], DRW_TEX_DEPTH_24, DRW_TEX_MIPMAP);
}
- DRW_framebuffer_init(&fbl->downsample_fb, &draw_engine_eevee_type,
- max_ii((int)viewport_size[0] / 2, 1), max_ii((int)viewport_size[1] / 2, 1),
- &texmax, 1);
-
+ if (fbl->downsample_fb == NULL) {
+ fbl->downsample_fb = GPU_framebuffer_create();
+ }
/**
* Compute Mipmap texel alignement.
@@ -179,34 +197,37 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
* Normal buffer for deferred passes.
*/
if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
- if (txl->ssr_normal_input == NULL) {
- DRWTextureFormat nor_format = DRW_TEX_RG_16;
- txl->ssr_normal_input = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1], nor_format, 0, NULL);
- }
+ int size_fs[2] = {(int)viewport_size[0], (int)viewport_size[1]};
- /* Reattach textures to the right buffer (because we are alternating between buffers) */
- /* TODO multiple FBO per texture!!!! */
- DRW_framebuffer_texture_detach(txl->ssr_normal_input);
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 1, 0);
+ effects->ssr_normal_input = DRW_texture_pool_query_2D(size_fs[0], size_fs[1], DRW_TEX_RG_16,
+ &draw_engine_eevee_type);
+
+ GPU_framebuffer_texture_attach(fbl->main_fb, effects->ssr_normal_input, 1, 0);
}
else {
- /* Cleanup to release memory */
- DRW_TEXTURE_FREE_SAFE(txl->ssr_normal_input);
+ effects->ssr_normal_input = NULL;
}
/**
* Setup double buffer so we can access last frame as it was before post processes.
*/
if ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0) {
- DRWFboTexture tex_double_buffer = {&txl->color_double_buffer, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
- DRW_framebuffer_init(&fbl->double_buffer, &draw_engine_eevee_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex_double_buffer, 1);
+ DRW_texture_ensure_fullscreen_2D(&txl->color_double_buffer, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP);
+
+ GPU_framebuffer_ensure_config(&fbl->double_buffer_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(txl->color_double_buffer)
+ });
+
+ GPU_framebuffer_ensure_config(&fbl->double_buffer_color_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->color_double_buffer)
+ });
}
else {
/* Cleanup to release memory */
DRW_TEXTURE_FREE_SAFE(txl->color_double_buffer);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->double_buffer);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->double_buffer_fb);
}
}
@@ -227,75 +248,47 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
psl->color_downsample_ps = DRW_pass_create("Downsample", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.downsample_sh, psl->color_downsample_ps);
- DRW_shgroup_uniform_buffer(grp, "source", &e_data.color_src);
+ DRW_shgroup_uniform_texture_ref(grp, "source", &e_data.color_src);
DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1);
DRW_shgroup_call_add(grp, quad, NULL);
}
{
static int zero = 0;
+ static unsigned int six = 6;
psl->color_downsample_cube_ps = DRW_pass_create("Downsample Cube", DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.downsample_cube_sh, psl->color_downsample_cube_ps, quad);
- DRW_shgroup_uniform_buffer(grp, "source", &e_data.color_src);
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.downsample_cube_sh, psl->color_downsample_cube_ps);
+ DRW_shgroup_uniform_texture_ref(grp, "source", &e_data.color_src);
DRW_shgroup_uniform_float(grp, "texelSize", &e_data.cube_texel_size, 1);
DRW_shgroup_uniform_int(grp, "Layer", &zero, 1);
- DRW_shgroup_set_instance_count(grp, 6);
+ DRW_shgroup_call_instances_add(grp, quad, NULL, &six);
}
{
/* Perform min/max downsample */
DRWShadingGroup *grp;
-#if 0 /* Not used for now */
- psl->minz_downlevel_ps = DRW_pass_create("HiZ Min Down Level", downsample_write | DRW_STATE_DEPTH_ALWAYS);
- grp = DRW_shgroup_create(e_data.minz_downlevel_sh, psl->minz_downlevel_ps);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &stl->g_data->minzbuffer);
- DRW_shgroup_call_add(grp, quad, NULL);
-#endif
-
psl->maxz_downlevel_ps = DRW_pass_create("HiZ Max Down Level", downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_downlevel_sh, psl->maxz_downlevel_ps);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &txl->maxzbuffer);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &txl->maxzbuffer);
DRW_shgroup_call_add(grp, quad, NULL);
/* Copy depth buffer to halfres top level of HiZ */
-#if 0 /* Not used for now */
- psl->minz_downdepth_ps = DRW_pass_create("HiZ Min Copy Depth Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
- grp = DRW_shgroup_create(e_data.minz_downdepth_sh, psl->minz_downdepth_ps);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
- DRW_shgroup_call_add(grp, quad, NULL);
-#endif
psl->maxz_downdepth_ps = DRW_pass_create("HiZ Max Copy Depth Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_downdepth_sh, psl->maxz_downdepth_ps);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
- DRW_shgroup_call_add(grp, quad, NULL);
-
-#if 0 /* Not used for now */
- psl->minz_downdepth_layer_ps = DRW_pass_create("HiZ Min Copy DepthLayer Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
- grp = DRW_shgroup_create(e_data.minz_downdepth_layer_sh, psl->minz_downdepth_layer_ps);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
- DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_call_add(grp, quad, NULL);
-#endif
psl->maxz_downdepth_layer_ps = DRW_pass_create("HiZ Max Copy DepthLayer Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_downdepth_layer_sh, psl->maxz_downdepth_layer_ps);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1);
DRW_shgroup_call_add(grp, quad, NULL);
- /* Copy depth buffer to halfres top level of HiZ */
-#if 0 /* Not used for now */
- psl->minz_copydepth_ps = DRW_pass_create("HiZ Min Copy Depth Fullres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
- grp = DRW_shgroup_create(e_data.minz_copydepth_sh, psl->minz_copydepth_ps);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
- DRW_shgroup_call_add(grp, quad, NULL);
-#endif
-
psl->maxz_copydepth_ps = DRW_pass_create("HiZ Max Copy Depth Fullres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_copydepth_sh, psl->maxz_copydepth_ps);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_call_add(grp, quad, NULL);
}
}
@@ -339,130 +332,98 @@ void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, GPUTexture *depth_src, int l
#if 0 /* Not required for now */
DRW_stats_group_start("Min buffer");
/* Copy depth buffer to min texture top level */
- DRW_framebuffer_texture_attach(fbl->downsample_fb, stl->g_data->minzbuffer, 0, 0);
- DRW_framebuffer_bind(fbl->downsample_fb);
+ GPU_framebuffer_texture_attach(fbl->downsample_fb, stl->g_data->minzbuffer, 0, 0);
+ GPU_framebuffer_bind(fbl->downsample_fb);
if (layer >= 0) {
DRW_draw_pass(psl->minz_downdepth_layer_ps);
}
else {
DRW_draw_pass(psl->minz_downdepth_ps);
}
- DRW_framebuffer_texture_detach(stl->g_data->minzbuffer);
+ GPU_framebuffer_texture_detach(stl->g_data->minzbuffer);
/* Create lower levels */
- DRW_framebuffer_recursive_downsample(fbl->downsample_fb, stl->g_data->minzbuffer, 8, &min_downsample_cb, vedata);
+ GPU_framebuffer_recursive_downsample(fbl->downsample_fb, stl->g_data->minzbuffer, 8, &min_downsample_cb, vedata);
DRW_stats_group_end();
#endif
DRW_stats_group_start("Max buffer");
/* Copy depth buffer to max texture top level */
- DRW_framebuffer_texture_attach(fbl->downsample_fb, txl->maxzbuffer, 0, 0);
- DRW_framebuffer_bind(fbl->downsample_fb);
+ GPU_framebuffer_texture_attach(fbl->downsample_fb, txl->maxzbuffer, 0, 0);
+ GPU_framebuffer_bind(fbl->downsample_fb);
if (layer >= 0) {
DRW_draw_pass(psl->maxz_downdepth_layer_ps);
}
else {
DRW_draw_pass(psl->maxz_downdepth_ps);
}
- DRW_framebuffer_texture_detach(txl->maxzbuffer);
/* Create lower levels */
- DRW_framebuffer_recursive_downsample(fbl->downsample_fb, txl->maxzbuffer, 8, &max_downsample_cb, vedata);
+ GPU_framebuffer_recursive_downsample(fbl->downsample_fb, 8, &max_downsample_cb, vedata);
+ GPU_framebuffer_texture_detach(fbl->downsample_fb, txl->maxzbuffer);
DRW_stats_group_end();
/* Restore */
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_bind(fbl->main_fb);
}
/**
* Simple downsampling algorithm. Reconstruct mip chain up to mip level.
**/
-void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, GPUTexture *texture_src, int level)
+void EEVEE_downsample_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, int level)
{
+ EEVEE_FramebufferList *fbl = vedata->fbl;
e_data.color_src = texture_src;
- DRW_stats_group_start("Downsample buffer");
/* Create lower levels */
- DRW_framebuffer_recursive_downsample(fb_src, texture_src, level, &simple_downsample_cb, vedata);
+ DRW_stats_group_start("Downsample buffer");
+ GPU_framebuffer_texture_attach(fbl->downsample_fb, texture_src, 0, 0);
+ GPU_framebuffer_recursive_downsample(fbl->downsample_fb, level, &simple_downsample_cb, vedata);
+ GPU_framebuffer_texture_detach(fbl->downsample_fb, texture_src);
DRW_stats_group_end();
}
/**
* Simple downsampling algorithm for cubemap. Reconstruct mip chain up to mip level.
**/
-void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, GPUTexture *texture_src, int level)
+void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, int level)
{
+ EEVEE_FramebufferList *fbl = vedata->fbl;
e_data.color_src = texture_src;
- DRW_stats_group_start("Downsample Cube buffer");
/* Create lower levels */
- DRW_framebuffer_recursive_downsample(fb_src, texture_src, level, &simple_downsample_cube_cb, vedata);
+ DRW_stats_group_start("Downsample Cube buffer");
+ GPU_framebuffer_texture_attach(fbl->downsample_fb, texture_src, 0, 0);
+ GPU_framebuffer_recursive_downsample(fbl->downsample_fb, level, &simple_downsample_cube_cb, vedata);
+ GPU_framebuffer_texture_detach(fbl->downsample_fb, texture_src);
DRW_stats_group_end();
}
-void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_TextureList *txl = vedata->txl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
- DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
/* only once per frame after the first post process */
effects->swap_double_buffer = ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0);
/* Init pointers */
effects->source_buffer = txl->color; /* latest updated texture */
- effects->target_buffer = fbl->effect_fb; /* next target to render to */
+ effects->target_buffer = fbl->effect_color_fb; /* next target to render to */
/* Temporal Anti-Aliasing MUST come first */
EEVEE_temporal_sampling_draw(vedata);
- /* Detach depth for effects to use it */
- DRW_framebuffer_texture_detach(dtxl->depth);
-
/* Post process stack (order matters) */
EEVEE_motion_blur_draw(vedata);
EEVEE_depth_of_field_draw(vedata);
EEVEE_bloom_draw(vedata);
- /* Restore default framebuffer */
- DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
- DRW_framebuffer_bind(dfbl->default_fb);
-
- /* Tonemapping */
- DRW_transform_to_display(effects->source_buffer);
-
- /* Debug : Ouput buffer to view. */
- switch (G.debug_value) {
- case 1:
- if (txl->maxzbuffer) DRW_transform_to_display(txl->maxzbuffer);
- break;
- case 2:
- if (stl->g_data->ssr_pdf_output) DRW_transform_to_display(stl->g_data->ssr_pdf_output);
- break;
- case 3:
- if (txl->ssr_normal_input) DRW_transform_to_display(txl->ssr_normal_input);
- break;
- case 4:
- if (txl->ssr_specrough_input) DRW_transform_to_display(txl->ssr_specrough_input);
- break;
- case 5:
- if (txl->color_double_buffer) DRW_transform_to_display(txl->color_double_buffer);
- break;
- case 6:
- if (stl->g_data->gtao_horizons_debug) DRW_transform_to_display(stl->g_data->gtao_horizons_debug);
- break;
- case 7:
- if (txl->gtao_horizons) DRW_transform_to_display(txl->gtao_horizons);
- break;
- case 8:
- if (txl->sss_data) DRW_transform_to_display(txl->sss_data);
- break;
- default:
- break;
- }
+ /* Save the final texture and framebuffer for final transformation or read. */
+ effects->final_tx = effects->source_buffer;
+ effects->final_fb = (effects->target_buffer != fbl->main_fb) ? fbl->main_fb : fbl->effect_fb;
/* If no post processes is enabled, buffers are still not swapped, do it now. */
SWAP_DOUBLE_BUFFERS();
@@ -477,7 +438,7 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
/* Record pers matrix for the next frame. */
- DRW_viewport_matrix_get(sldata->common_data.prev_persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_get(stl->effects->prev_persmat, DRW_MAT_PERS);
/* Update double buffer status if render mode. */
if (DRW_state_is_image_render()) {
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index fe2beb4b557..276f23c7cf7 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -29,9 +29,13 @@
#include "BLI_rand.h"
#include "BKE_object.h"
+#include "BKE_global.h" /* for G.debug_value */
+#include "BKE_screen.h"
#include "DNA_world_types.h"
+#include "ED_screen.h"
+
#include "GPU_material.h"
#include "GPU_glew.h"
@@ -51,6 +55,12 @@ static void eevee_engine_init(void *ved)
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ RegionView3D *rv3d = draw_ctx->rv3d;
+ Object *camera = (rv3d->persp == RV3D_CAMOB) ? v3d->camera : NULL;
if (!stl->g_data) {
/* Alloc transient pointers */
@@ -59,44 +69,52 @@ static void eevee_engine_init(void *ved)
stl->g_data->background_alpha = DRW_state_draw_background() ? 1.0f : 0.0f;
stl->g_data->valid_double_buffer = (txl->color_double_buffer != NULL);
- DRWFboTexture tex = {&txl->color, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
+ /* Main Buffer */
+ DRW_texture_ensure_fullscreen_2D(&txl->color, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP);
- const float *viewport_size = DRW_viewport_size_get();
- DRW_framebuffer_init(&fbl->main, &draw_engine_eevee_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex, 1);
+ GPU_framebuffer_ensure_config(&fbl->main_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(txl->color),
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE
+ });
+
+ GPU_framebuffer_ensure_config(&fbl->main_color_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->color)
+ });
if (sldata->common_ubo == NULL) {
sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), &sldata->common_data);
}
+ if (sldata->clip_ubo == NULL) {
+ sldata->clip_ubo = DRW_uniformbuffer_create(sizeof(sldata->clip_data), &sldata->clip_data);
+ }
/* EEVEE_effects_init needs to go first for TAA */
- EEVEE_effects_init(sldata, vedata);
-
+ EEVEE_effects_init(sldata, vedata, camera);
EEVEE_materials_init(sldata, stl, fbl);
EEVEE_lights_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
if ((stl->effects->taa_current_sample > 1) && !DRW_state_is_image_render()) {
/* XXX otherwise it would break the other engines. */
- DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
- DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_unset(DRW_MAT_WIN);
- DRW_viewport_matrix_override_unset(DRW_MAT_WININV);
+ DRW_viewport_matrix_override_unset_all();
}
}
static void eevee_cache_init(void *vedata)
{
- EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
EEVEE_bloom_cache_init(sldata, vedata);
EEVEE_depth_of_field_cache_init(sldata, vedata);
EEVEE_effects_cache_init(sldata, vedata);
EEVEE_lightprobes_cache_init(sldata, vedata);
- EEVEE_lights_cache_init(sldata, psl);
- EEVEE_materials_cache_init(vedata);
+ EEVEE_lights_cache_init(sldata, vedata);
+ EEVEE_materials_cache_init(sldata, vedata);
EEVEE_motion_blur_cache_init(sldata, vedata);
EEVEE_occlusion_cache_init(sldata, vedata);
EEVEE_screen_raytrace_cache_init(sldata, vedata);
@@ -160,36 +178,61 @@ static void eevee_cache_finish(void *vedata)
static void eevee_draw_background(void *vedata)
{
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl;
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
EEVEE_FramebufferList *fbl = ((EEVEE_Data *)vedata)->fbl;
+ EEVEE_EffectsInfo *effects = stl->effects;
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
/* Default framebuffer and texture */
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+
+ /* Sort transparents before the loop. */
+ DRW_pass_sort_shgroup_z(psl->transparent_pass);
- /* Number of iteration: needed for all temporal effect (SSR, TAA)
+ /* Number of iteration: needed for all temporal effect (SSR, volumetrics)
* when using opengl render. */
- int loop_ct = DRW_state_is_image_render() ? 4 : 1;
+ int loop_ct = (DRW_state_is_image_render() &&
+ (stl->effects->enabled_effects & (EFFECT_VOLUMETRIC | EFFECT_SSR)) != 0) ? 4 : 1;
while (loop_ct--) {
+ float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float clear_depth = 1.0f;
+ unsigned int clear_stencil = 0xFF;
unsigned int primes[3] = {2, 3, 7};
double offset[3] = {0.0, 0.0, 0.0};
double r[3];
- if (DRW_state_is_image_render()) {
+ if (DRW_state_is_image_render() ||
+ ((stl->effects->enabled_effects & EFFECT_TAA) != 0))
+ {
BLI_halton_3D(primes, offset, stl->effects->taa_current_sample, r);
- /* Set jitter offset */
EEVEE_update_noise(psl, fbl, r);
+ EEVEE_volumes_set_jitter(sldata, stl->effects->taa_current_sample - 1);
+ EEVEE_materials_init(sldata, stl, fbl);
}
- else if ((stl->effects->enabled_effects & EFFECT_TAA) != 0) {
- BLI_halton_3D(primes, offset, stl->effects->taa_current_sample, r);
- /* Set jitter offset */
- EEVEE_update_noise(psl, fbl, r);
+ /* Copy previous persmat to UBO data */
+ copy_m4_m4(sldata->common_data.prev_persmat, stl->effects->prev_persmat);
+
+ if (((stl->effects->enabled_effects & EFFECT_TAA) != 0) &&
+ (stl->effects->taa_current_sample > 1) &&
+ !DRW_state_is_image_render())
+ {
+ DRW_viewport_matrix_override_set(stl->effects->overide_persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_override_set(stl->effects->overide_persinv, DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_set(stl->effects->overide_winmat, DRW_MAT_WIN);
+ DRW_viewport_matrix_override_set(stl->effects->overide_wininv, DRW_MAT_WININV);
}
/* Refresh Probes */
DRW_stats_group_start("Probes Refresh");
EEVEE_lightprobes_refresh(sldata, vedata);
+ /* Probes refresh can have reset the current sample. */
+ if (stl->effects->taa_current_sample == 1) {
+ DRW_viewport_matrix_override_unset_all();
+ }
+ EEVEE_lightprobes_refresh_planar(sldata, vedata);
DRW_stats_group_end();
/* Update common buffer after probe rendering. */
@@ -200,28 +243,11 @@ static void eevee_draw_background(void *vedata)
EEVEE_draw_shadows(sldata, psl);
DRW_stats_group_end();
- /* Attach depth to the hdr buffer and bind it */
- DRW_framebuffer_texture_detach(dtxl->depth);
- DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
- DRW_framebuffer_bind(fbl->main);
- if (DRW_state_draw_background()) {
- DRW_framebuffer_clear(false, true, true, NULL, 1.0f);
- }
- else {
- /* We need to clear the alpha chanel in this case. */
- float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- DRW_framebuffer_clear(true, true, true, clear_col, 1.0f);
- }
-
- if (((stl->effects->enabled_effects & EFFECT_TAA) != 0) &&
- (stl->effects->taa_current_sample > 1) &&
- !DRW_state_is_image_render())
- {
- DRW_viewport_matrix_override_set(stl->effects->overide_persmat, DRW_MAT_PERS);
- DRW_viewport_matrix_override_set(stl->effects->overide_persinv, DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_set(stl->effects->overide_winmat, DRW_MAT_WIN);
- DRW_viewport_matrix_override_set(stl->effects->overide_wininv, DRW_MAT_WININV);
- }
+ GPU_framebuffer_bind(fbl->main_fb);
+ GPUFrameBufferBits clear_bits = GPU_DEPTH_BIT;
+ clear_bits |= (DRW_state_draw_background()) ? 0 : GPU_COLOR_BIT;
+ clear_bits |= ((stl->effects->enabled_effects & EFFECT_SSS) != 0) ? GPU_STENCIL_BIT : 0;
+ GPU_framebuffer_clear(fbl->main_fb, clear_bits, clear_col, clear_depth, clear_stencil);
/* Depth prepass */
DRW_stats_group_start("Prepass");
@@ -265,7 +291,6 @@ static void eevee_draw_background(void *vedata)
EEVEE_volumes_resolve(sldata, vedata);
/* Transparent */
- DRW_pass_sort_shgroup_z(psl->transparent_pass);
DRW_draw_pass(psl->transparent_pass);
/* Post Process */
@@ -274,13 +299,44 @@ static void eevee_draw_background(void *vedata)
DRW_stats_group_end();
if ((stl->effects->taa_current_sample > 1) && !DRW_state_is_image_render()) {
- DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
- DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_unset(DRW_MAT_WIN);
- DRW_viewport_matrix_override_unset(DRW_MAT_WININV);
+ DRW_viewport_matrix_override_unset_all();
}
}
+ /* Tonemapping and transfer result to default framebuffer. */
+ GPU_framebuffer_bind(dfbl->default_fb);
+ DRW_transform_to_display(stl->effects->final_tx);
+
+ /* Debug : Ouput buffer to view. */
+ switch (G.debug_value) {
+ case 1:
+ if (txl->maxzbuffer) DRW_transform_to_display(txl->maxzbuffer);
+ break;
+ case 2:
+ if (effects->ssr_pdf_output) DRW_transform_to_display(effects->ssr_pdf_output);
+ break;
+ case 3:
+ if (effects->ssr_normal_input) DRW_transform_to_display(effects->ssr_normal_input);
+ break;
+ case 4:
+ if (effects->ssr_specrough_input) DRW_transform_to_display(effects->ssr_specrough_input);
+ break;
+ case 5:
+ if (txl->color_double_buffer) DRW_transform_to_display(txl->color_double_buffer);
+ break;
+ case 6:
+ if (effects->gtao_horizons_debug) DRW_transform_to_display(effects->gtao_horizons_debug);
+ break;
+ case 7:
+ if (effects->gtao_horizons) DRW_transform_to_display(effects->gtao_horizons);
+ break;
+ case 8:
+ if (effects->sss_data) DRW_transform_to_display(effects->sss_data);
+ break;
+ default:
+ break;
+ }
+
EEVEE_volumes_free_smoke_textures();
stl->g_data->view_updated = false;
@@ -294,33 +350,52 @@ static void eevee_view_update(void *vedata)
}
}
-static void eevee_id_update(void *UNUSED(vedata), ID *id)
+static void eevee_id_object_update(void *UNUSED(vedata), Object *object)
{
/* This is a bit mask of components which update is to be ignored. */
const int ignore_updates = ID_RECALC_COLLECTIONS;
- /* Check whether we have to do anything here. */
- if ((id->recalc & ~ignore_updates) == 0) {
- return;
+ const int allowed_updates = ~ignore_updates;
+ EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_get(object);
+ if (ped != NULL && (ped->engine_data.recalc & allowed_updates) != 0) {
+ ped->need_full_update = true;
+ ped->engine_data.recalc = 0;
+ }
+ EEVEE_LampEngineData *led = EEVEE_lamp_data_get(object);
+ if (led != NULL && (led->engine_data.recalc & allowed_updates) != 0) {
+ led->need_update = true;
+ led->engine_data.recalc = 0;
+ }
+ EEVEE_ObjectEngineData *oedata = EEVEE_object_data_get(object);
+ if (oedata != NULL && (oedata->engine_data.recalc & allowed_updates) != 0) {
+ oedata->need_update = true;
+ oedata->engine_data.recalc = 0;
}
+}
+
+static void eevee_id_update(void *vedata, ID *id)
+{
/* Handle updates based on ID type. */
- const ID_Type id_type = GS(id->name);
- if (id_type == ID_OB) {
- Object *object = (Object *)id;
- EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_get(object);
- if (ped != NULL) {
- ped->need_full_update = true;
- }
- EEVEE_LampEngineData *led = EEVEE_lamp_data_get(object);
- if (led != NULL) {
- led->need_update = true;
- }
- EEVEE_ObjectEngineData *oedata = EEVEE_object_data_get(object);
- if (oedata != NULL) {
- oedata->need_update = true;
- }
+ switch (GS(id->name)) {
+ case ID_OB:
+ eevee_id_object_update(vedata, (Object *)id);
+ break;
+ default:
+ /* pass */
+ break;
}
}
+static void eevee_render_to_image(void *vedata, RenderEngine *engine, struct RenderLayer *render_layer, const rcti *rect)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ EEVEE_render_init(vedata, engine, draw_ctx->depsgraph);
+
+ DRW_render_object_iter(vedata, engine, draw_ctx->depsgraph, EEVEE_render_cache);
+
+ /* Actually do the rendering. */
+ EEVEE_render_draw(vedata, engine, render_layer, rect);
+}
+
static void eevee_engine_free(void)
{
EEVEE_bloom_free();
@@ -329,6 +404,7 @@ static void eevee_engine_free(void)
EEVEE_lightprobes_free();
EEVEE_lights_free();
EEVEE_materials_free();
+ EEVEE_mist_free();
EEVEE_motion_blur_free();
EEVEE_occlusion_free();
EEVEE_screen_raytrace_free();
@@ -356,7 +432,8 @@ static void eevee_view_layer_settings_create(RenderEngine *UNUSED(engine), IDPro
BKE_collection_engine_property_add_int(props, "gi_cubemap_resolution", 512);
BKE_collection_engine_property_add_int(props, "gi_visibility_resolution", 32);
- BKE_collection_engine_property_add_int(props, "taa_samples", 8);
+ BKE_collection_engine_property_add_int(props, "taa_samples", 16);
+ BKE_collection_engine_property_add_int(props, "taa_render_samples", 64);
BKE_collection_engine_property_add_bool(props, "sss_enable", false);
BKE_collection_engine_property_add_int(props, "sss_samples", 7);
@@ -428,12 +505,14 @@ DrawEngineType draw_engine_eevee_type = {
NULL, /* Everything is drawn in the background pass (see comment on function) */
&eevee_view_update,
&eevee_id_update,
+ &eevee_render_to_image,
};
RenderEngineType DRW_engine_viewport_eevee_type = {
NULL, NULL,
- EEVEE_ENGINE, N_("Eevee"), RE_INTERNAL | RE_USE_SHADING_NODES,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ EEVEE_ENGINE, N_("Eevee"), RE_INTERNAL | RE_USE_SHADING_NODES | RE_USE_PREVIEW,
+ NULL, &DRW_render_to_image, NULL, NULL, NULL, NULL,
+ &EEVEE_render_update_passes,
&eevee_layer_collection_settings_create,
&eevee_view_layer_settings_create,
&draw_engine_eevee_type,
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 7403da737dd..59e8e76bc52 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -36,6 +36,7 @@
#include "DNA_view3d_types.h"
#include "BKE_object.h"
+#include "MEM_guardedalloc.h"
#include "GPU_material.h"
#include "GPU_texture.h"
@@ -82,7 +83,8 @@ static struct {
struct GPUTexture *depth_array_placeholder;
struct GPUTexture *cube_face_minmaxz;
- int update_world;
+ struct Gwn_VertFormat *format_probe_display_cube;
+ struct Gwn_VertFormat *format_probe_display_planar;
} e_data = {NULL}; /* Engine data */
extern char datatoc_background_vert_glsl[];
@@ -107,6 +109,7 @@ extern char datatoc_lightprobe_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
extern GlobalsUboStorage ts;
@@ -152,7 +155,6 @@ static void planar_pool_ensure_alloc(EEVEE_Data *vedata, int num_planar_ref)
/* XXX TODO OPTIMISATION : This is a complete waist of texture memory.
* Instead of allocating each planar probe for each viewport,
* only alloc them once using the biggest viewport resolution. */
- EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
const float *viewport_size = DRW_viewport_size_get();
@@ -179,15 +181,6 @@ static void planar_pool_ensure_alloc(EEVEE_Data *vedata, int num_planar_ref)
txl->planar_depth = DRW_texture_create_2D_array(1, 1, 1, DRW_TEX_DEPTH_24, 0, NULL);
}
}
-
- if (num_planar_ref > 0) {
- /* NOTE : Depth buffer is 2D but the planar_pool tex is 2D array.
- * DRW_framebuffer_init binds the whole texture making the framebuffer invalid.
- * To overcome this, we bind the planar pool ourselves later */
-
- /* XXX Do this one first so it gets it's mipmap done. */
- DRW_framebuffer_init(&fbl->planarref_fb, &draw_engine_eevee_type, 1, 1, NULL, 0);
- }
}
static void lightprobe_shaders_init(void)
@@ -203,8 +196,10 @@ static void lightprobe_shaders_init(void)
"#define NOISE_SIZE 64\n";
char *shader_str = NULL;
+ char *vert_str = NULL;
shader_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
@@ -219,6 +214,7 @@ static void lightprobe_shaders_init(void)
MEM_freeN(shader_str);
shader_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
@@ -229,6 +225,7 @@ static void lightprobe_shaders_init(void)
MEM_freeN(shader_str);
shader_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
@@ -240,15 +237,20 @@ static void lightprobe_shaders_init(void)
shader_str = BLI_string_joinN(
datatoc_octahedron_lib_glsl,
+ datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_irradiance_lib_glsl,
datatoc_lightprobe_lib_glsl,
datatoc_lightprobe_grid_display_frag_glsl);
- e_data.probe_grid_display_sh = DRW_shader_create(
- datatoc_lightprobe_grid_display_vert_glsl, NULL, shader_str, filter_defines);
+ vert_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl,
+ datatoc_lightprobe_grid_display_vert_glsl);
+
+ e_data.probe_grid_display_sh = DRW_shader_create(vert_str, NULL, shader_str, filter_defines);
+ MEM_freeN(vert_str);
MEM_freeN(shader_str);
e_data.probe_grid_fill_sh = DRW_shader_create_fullscreen(
@@ -256,19 +258,33 @@ static void lightprobe_shaders_init(void)
shader_str = BLI_string_joinN(
datatoc_octahedron_lib_glsl,
+ datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_lightprobe_lib_glsl,
datatoc_lightprobe_cube_display_frag_glsl);
- e_data.probe_cube_display_sh = DRW_shader_create(
- datatoc_lightprobe_cube_display_vert_glsl, NULL, shader_str, NULL);
+ vert_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl,
+ datatoc_lightprobe_cube_display_vert_glsl);
+ e_data.probe_cube_display_sh = DRW_shader_create(vert_str, NULL, shader_str, NULL);
+
+ MEM_freeN(vert_str);
MEM_freeN(shader_str);
- e_data.probe_planar_display_sh = DRW_shader_create(
- datatoc_lightprobe_planar_display_vert_glsl, NULL,
- datatoc_lightprobe_planar_display_frag_glsl, NULL);
+ vert_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl,
+ datatoc_lightprobe_planar_display_vert_glsl);
+
+ shader_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl,
+ datatoc_lightprobe_planar_display_frag_glsl);
+
+ e_data.probe_planar_display_sh = DRW_shader_create(vert_str, NULL, shader_str, NULL);
+
+ MEM_freeN(vert_str);
+ MEM_freeN(shader_str);
e_data.probe_planar_downsample_sh = DRW_shader_create(
datatoc_lightprobe_planar_downsample_vert_glsl,
@@ -300,6 +316,9 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda
sldata->planar_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_PlanarReflection) * MAX_PLANAR, NULL);
}
+ /* Only start doing probes if all materials have finished compiling. */
+ sldata->probes->all_materials_updated = true;
+
common_data->spec_toggle = true;
common_data->ssr_toggle = true;
common_data->sss_toggle = true;
@@ -317,6 +336,7 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda
sldata->probes->target_size = prop_cubemap_res >> 1;
+ DRW_TEXTURE_FREE_SAFE(sldata->probe_depth_rt);
DRW_TEXTURE_FREE_SAFE(sldata->probe_rt);
DRW_TEXTURE_FREE_SAFE(sldata->probe_pool);
}
@@ -328,7 +348,7 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda
}
if (update_all) {
- e_data.update_world |= PROBE_UPDATE_ALL;
+ sldata->probes->update_world |= PROBE_UPDATE_ALL;
sldata->probes->updated_bounce = 0;
sldata->probes->grid_initialized = false;
}
@@ -339,13 +359,12 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda
sldata->probe_rt = DRW_texture_create_cube(sldata->probes->target_size, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
}
- DRWFboTexture tex_probe[2] = {{&sldata->probe_depth_rt, DRW_TEX_DEPTH_24, 0},
- {&sldata->probe_rt, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP}};
- DRW_framebuffer_init(&sldata->probe_fb, &draw_engine_eevee_type, sldata->probes->target_size, sldata->probes->target_size, tex_probe, 2);
-
- /* Minmaxz Pyramid */
- // DRWFboTexture tex_minmaxz = {&e_data.cube_face_minmaxz, DRW_TEX_RG_32, DRW_TEX_MIPMAP | DRW_TEX_TEMP};
- // DRW_framebuffer_init(&vedata->fbl->downsample_fb, &draw_engine_eevee_type, PROBE_RT_SIZE / 2, PROBE_RT_SIZE / 2, &tex_minmaxz, 1);
+ for (int i = 0; i < 6; ++i) {
+ GPU_framebuffer_ensure_config(&sldata->probe_face_fb[i], {
+ GPU_ATTACHMENT_TEXTURE_CUBEFACE(sldata->probe_depth_rt, i),
+ GPU_ATTACHMENT_TEXTURE_CUBEFACE(sldata->probe_rt, i)
+ });
+ }
/* Placeholder planar pool: used when rendering planar reflections (avoid dependency loop). */
if (!e_data.planar_pool_placeholder) {
@@ -389,36 +408,47 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
float *col = ts.colorBackground;
if (wo) {
col = &wo->horr;
- if (wo->update_flag != 0 || pinfo->prev_world != wo) {
- e_data.update_world |= PROBE_UPDATE_ALL;
- pinfo->updated_bounce = 0;
- pinfo->grid_initialized = false;
- }
- wo->update_flag = 0;
+ bool wo_sh_compiled = true;
if (wo->use_nodes && wo->nodetree) {
+ static float error_col[3] = {1.0f, 0.0f, 1.0f};
+ static float compile_col[3] = {0.5f, 0.5f, 0.5f};
struct GPUMaterial *gpumat = EEVEE_material_world_lightprobe_get(scene, wo);
- grp = DRW_shgroup_material_create(gpumat, psl->probe_background);
-
- if (grp) {
- DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
- DRW_shgroup_call_add(grp, geom, NULL);
- }
- else {
- /* Shader failed : pink background */
- static float pink[3] = {1.0f, 0.0f, 1.0f};
- col = pink;
+ GPUMaterialStatus status = GPU_material_status(gpumat);
+
+ switch (status) {
+ case GPU_MAT_SUCCESS:
+ grp = DRW_shgroup_material_create(gpumat, psl->probe_background);
+ DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
+ DRW_shgroup_call_add(grp, geom, NULL);
+ wo_sh_compiled = true;
+ break;
+ case GPU_MAT_QUEUED:
+ pinfo->all_materials_updated = false;
+ wo_sh_compiled = false;
+ /* TODO Bypass probe compilation. */
+ col = compile_col;
+ break;
+ case GPU_MAT_FAILED:
+ default:
+ wo_sh_compiled = true;
+ col = error_col;
+ break;
}
}
- pinfo->prev_world = wo;
+ if (wo->update_flag != 0 || pinfo->prev_world != wo || pinfo->prev_wo_sh_compiled != wo_sh_compiled) {
+ pinfo->update_world |= PROBE_UPDATE_ALL;
+ pinfo->prev_wo_sh_compiled = wo_sh_compiled;
+ pinfo->prev_world = wo;
+ }
+ wo->update_flag = 0;
}
else if (pinfo->prev_world) {
+ pinfo->update_world |= PROBE_UPDATE_ALL;
+ pinfo->prev_wo_sh_compiled = false;
pinfo->prev_world = NULL;
- e_data.update_world |= PROBE_UPDATE_ALL;
- pinfo->updated_bounce = 0;
- pinfo->grid_initialized = false;
}
/* Fallback if shader fails or if not using nodetree. */
@@ -433,9 +463,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
{
psl->probe_glossy_compute = DRW_pass_create("LightProbe Glossy Compute", DRW_STATE_WRITE_COLOR);
- struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
-
- DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.probe_filter_glossy_sh, psl->probe_glossy_compute, geom);
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_filter_glossy_sh, psl->probe_glossy_compute);
DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1);
DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_ct, 1);
DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->invsamples_ct, 1);
@@ -448,8 +476,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
// DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
DRW_shgroup_uniform_texture(grp, "probeHdr", sldata->probe_rt);
-
- DRW_shgroup_set_instance_count(grp, 1);
+ DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
{
@@ -495,7 +522,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
psl->probe_grid_fill = DRW_pass_create("LightProbe Grid Floodfill", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_grid_fill_sh, psl->probe_grid_fill);
- DRW_shgroup_uniform_buffer(grp, "irradianceGrid", &sldata->irradiance_pool);
+ DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &sldata->irradiance_pool);
struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call_add(grp, geom, NULL);
@@ -505,28 +532,42 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK;
psl->probe_display = DRW_pass_create("LightProbe Display", state);
- struct Gwn_Batch *geom = DRW_cache_sphere_get();
- DRWShadingGroup *grp = stl->g_data->cube_display_shgrp = DRW_shgroup_instance_create(e_data.probe_cube_display_sh, psl->probe_display, geom);
- DRW_shgroup_attrib_float(grp, "probe_id", 1); /* XXX this works because we are still uploading 4bytes and using the right stride */
- DRW_shgroup_attrib_float(grp, "probe_location", 3);
- DRW_shgroup_attrib_float(grp, "sphere_size", 1);
- DRW_shgroup_uniform_buffer(grp, "probeCubes", &sldata->probe_pool);
+ DRW_shgroup_instance_format(e_data.format_probe_display_cube, {
+ {"probe_id", DRW_ATTRIB_INT, 1},
+ {"probe_location", DRW_ATTRIB_FLOAT, 3},
+ {"sphere_size", DRW_ATTRIB_FLOAT, 1},
+ });
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(
+ e_data.probe_cube_display_sh,
+ psl->probe_display,
+ DRW_cache_sphere_get(),
+ e_data.format_probe_display_cube);
+ stl->g_data->cube_display_shgrp = grp;
+ DRW_shgroup_uniform_texture_ref(grp, "probeCubes", &sldata->probe_pool);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- geom = DRW_cache_quad_get();
- grp = stl->g_data->planar_display_shgrp = DRW_shgroup_instance_create(e_data.probe_planar_display_sh, psl->probe_display, geom);
- DRW_shgroup_attrib_float(grp, "probe_id", 1); /* XXX this works because we are still uploading 4bytes and using the right stride */
- DRW_shgroup_attrib_float(grp, "probe_mat", 16);
- DRW_shgroup_uniform_buffer(grp, "probePlanars", &txl->planar_pool);
+ DRW_shgroup_instance_format(e_data.format_probe_display_planar, {
+ {"probe_id", DRW_ATTRIB_INT, 1},
+ {"probe_mat", DRW_ATTRIB_FLOAT, 16},
+ });
+
+ grp = DRW_shgroup_instance_create(
+ e_data.probe_planar_display_sh,
+ psl->probe_display,
+ DRW_cache_quad_get(),
+ e_data.format_probe_display_planar);
+ stl->g_data->planar_display_shgrp = grp;
+ DRW_shgroup_uniform_texture_ref(grp, "probePlanars", &txl->planar_pool);
}
{
psl->probe_planar_downsample_ps = DRW_pass_create("LightProbe Planar Downsample", DRW_STATE_WRITE_COLOR);
- struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
- DRWShadingGroup *grp = stl->g_data->planar_downsample = DRW_shgroup_instance_create(e_data.probe_planar_downsample_sh, psl->probe_planar_downsample_ps, geom);
- DRW_shgroup_uniform_buffer(grp, "source", &txl->planar_pool);
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_planar_downsample_sh, psl->probe_planar_downsample_ps);
+ DRW_shgroup_uniform_texture_ref(grp, "source", &txl->planar_pool);
DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1);
+ DRW_shgroup_call_instances_add(grp, DRW_cache_fullscreen_quad_get(), NULL, (unsigned int *)&pinfo->num_planar);
}
}
@@ -535,20 +576,40 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
EEVEE_LightProbesInfo *pinfo = sldata->probes;
LightProbe *probe = (LightProbe *)ob->data;
- /* Step 1 find all lamps in the scene and setup them */
if ((probe->type == LIGHTPROBE_TYPE_CUBE && pinfo->num_cube >= MAX_PROBE) ||
- (probe->type == LIGHTPROBE_TYPE_GRID && pinfo->num_grid >= MAX_PROBE))
+ (probe->type == LIGHTPROBE_TYPE_GRID && pinfo->num_grid >= MAX_PROBE) ||
+ (probe->type == LIGHTPROBE_TYPE_PLANAR && pinfo->num_grid >= MAX_PLANAR))
{
printf("Too much probes in the scene !!!\n");
return;
}
+ if (probe->type == LIGHTPROBE_TYPE_PLANAR) {
+ /* See if this planar probe is inside the view frustum. If not, no need to update it. */
+ /* NOTE: this could be bypassed if we want feedback loop mirrors for rendering. */
+ BoundBox bbox; float tmp[4][4];
+ const float min[3] = {-1.0f, -1.0f, -1.0f};
+ const float max[3] = { 1.0f, 1.0f, 1.0f};
+ BKE_boundbox_init_from_minmax(&bbox, min, max);
+
+ copy_m4_m4(tmp, ob->obmat);
+ normalize_v3(tmp[2]);
+ mul_v3_fl(tmp[2], probe->distinf);
+
+ for (int v = 0; v < 8; ++v) {
+ mul_m4_v3(tmp, bbox.vec[v]);
+ }
+ if (!DRW_culling_box_test(&bbox)) {
+ return; /* Culled */
+ }
+ }
+
EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
ped->num_cell = probe->grid_resolution_x * probe->grid_resolution_y * probe->grid_resolution_z;
if ((probe->type == LIGHTPROBE_TYPE_GRID) &&
- ((pinfo->total_irradiance_samples + ped->num_cell) >= MAX_IRRADIANCE_SAMPLES))
+ ((pinfo->total_irradiance_samples + ped->num_cell) >= MAX_IRRADIANCE_SAMPLES))
{
printf("Too much grid samples !!!\n");
return;
@@ -567,7 +628,7 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
}
}
- if (e_data.update_world) {
+ if (pinfo->update_world) {
ped->need_update = true;
ped->updated_cells = 0;
ped->updated_lvl = 0;
@@ -576,18 +637,20 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
pinfo->do_cube_update |= ped->need_update;
- if (probe->type == LIGHTPROBE_TYPE_CUBE) {
- pinfo->probes_cube_ref[pinfo->num_cube] = ob;
- pinfo->num_cube++;
- }
- else if (probe->type == LIGHTPROBE_TYPE_PLANAR) {
- pinfo->probes_planar_ref[pinfo->num_planar] = ob;
- pinfo->num_planar++;
- }
- else { /* GRID */
- pinfo->probes_grid_ref[pinfo->num_grid] = ob;
- pinfo->num_grid++;
- pinfo->total_irradiance_samples += ped->num_cell;
+ switch (probe->type) {
+ case LIGHTPROBE_TYPE_CUBE:
+ pinfo->probes_cube_ref[pinfo->num_cube] = ob;
+ pinfo->num_cube++;
+ break;
+ case LIGHTPROBE_TYPE_PLANAR:
+ pinfo->probes_planar_ref[pinfo->num_planar] = ob;
+ pinfo->num_planar++;
+ break;
+ case LIGHTPROBE_TYPE_GRID:
+ pinfo->probes_grid_ref[pinfo->num_grid] = ob;
+ pinfo->num_grid++;
+ pinfo->total_irradiance_samples += ped->num_cell;
+ break;
}
}
@@ -598,15 +661,34 @@ static void scale_m4_v3(float R[4][4], float v[3])
mul_v3_v3(R[i], v);
}
-static void EEVEE_planar_reflections_updates(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl)
+static void EEVEE_planar_reflections_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl)
+{
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ Object *ob;
+
+ for (int i = 0; (ob = pinfo->probes_planar_ref[i]) && (i < MAX_PLANAR); i++) {
+ LightProbe *probe = (LightProbe *)ob->data;
+ EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
+
+ ped->probe_id = i;
+
+ /* Debug Display */
+ if (DRW_state_draw_support() &&
+ (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA))
+ {
+ DRW_shgroup_call_dynamic_add(stl->g_data->planar_display_shgrp, &ped->probe_id, ob->obmat);
+ }
+ }
+}
+
+static void EEVEE_planar_reflections_updates(EEVEE_ViewLayerData *sldata)
{
EEVEE_LightProbesInfo *pinfo = sldata->probes;
Object *ob;
float mtx[4][4], normat[4][4], imat[4][4], rangemat[4][4];
- float viewmat[4][4], winmat[4][4];
+ float viewmat[4][4];
DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW);
- DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
zero_m4(rangemat);
rangemat[0][0] = rangemat[1][1] = rangemat[2][2] = 0.5f;
@@ -618,36 +700,27 @@ static void EEVEE_planar_reflections_updates(EEVEE_ViewLayerData *sldata, EEVEE_
LightProbe *probe = (LightProbe *)ob->data;
EEVEE_PlanarReflection *eplanar = &pinfo->planar_data[i];
EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
-
/* Computing mtx : matrix that mirror position around object's XY plane. */
normalize_m4_m4(normat, ob->obmat); /* object > world */
invert_m4_m4(imat, normat); /* world > object */
-
float reflect[3] = {1.0f, 1.0f, -1.0f}; /* XY reflection plane */
scale_m4_v3(imat, reflect); /* world > object > mirrored obj */
mul_m4_m4m4(mtx, normat, imat); /* world > object > mirrored obj > world */
-
/* Reflect Camera Matrix. */
- mul_m4_m4m4(ped->viewmat, viewmat, mtx);
-
+ mul_m4_m4m4(ped->mats.mat[DRW_MAT_VIEW], viewmat, mtx);
/* TODO FOV margin */
- float winmat_fov[4][4];
- copy_m4_m4(winmat_fov, winmat);
-
- /* Apply Perspective Matrix. */
- mul_m4_m4m4(ped->persmat, winmat_fov, ped->viewmat);
-
+ /* Temporal sampling jitter should be already applied to the DRW_MAT_WIN. */
+ DRW_viewport_matrix_get(ped->mats.mat[DRW_MAT_WIN], DRW_MAT_WIN);
+ /* Apply Projection Matrix. */
+ mul_m4_m4m4(ped->mats.mat[DRW_MAT_PERS], ped->mats.mat[DRW_MAT_WIN], ped->mats.mat[DRW_MAT_VIEW]);
/* This is the matrix used to reconstruct texture coordinates.
* We use the original view matrix because it does not create
* visual artifacts if receiver is not perfectly aligned with
* the planar reflection probe. */
- mul_m4_m4m4(eplanar->reflectionmat, winmat_fov, viewmat); /* TODO FOV margin */
+ mul_m4_m4m4(eplanar->reflectionmat, ped->mats.mat[DRW_MAT_WIN], viewmat); /* TODO FOV margin */
/* Convert from [-1, 1] to [0, 1] (NDC to Texture coord). */
mul_m4_m4m4(eplanar->reflectionmat, rangemat, eplanar->reflectionmat);
- /* TODO frustum check. */
- ped->need_update = true;
-
/* Compute clip plane equation / normal. */
float refpoint[3];
copy_v3_v3(eplanar->plane_equation, ob->obmat[2]);
@@ -692,13 +765,6 @@ static void EEVEE_planar_reflections_updates(EEVEE_ViewLayerData *sldata, EEVEE_
float min_dist = min_ff(1.0f - 1e-8f, 1.0f - probe->falloff) * probe->distinf;
eplanar->attenuation_scale = -1.0f / max_ff(1e-8f, max_dist - min_dist);
eplanar->attenuation_bias = max_dist * -eplanar->attenuation_scale;
-
- /* Debug Display */
- if (DRW_state_draw_support() &&
- (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA))
- {
- DRW_shgroup_call_dynamic_add(stl->g_data->planar_display_shgrp, &ped->probe_id, ob->obmat);
- }
}
}
@@ -818,25 +884,25 @@ static void EEVEE_lightprobes_updates(EEVEE_ViewLayerData *sldata, EEVEE_PassLis
/* Visibility bias */
egrid->visibility_bias = 0.05f * probe->vis_bias;
egrid->visibility_bleed = probe->vis_bleedbias;
- egrid->visibility_range = max_ff(max_ff(len_v3(egrid->increment_x),
- len_v3(egrid->increment_y)),
- len_v3(egrid->increment_z)) + 1.0f;
+ egrid->visibility_range = (
+ sqrtf(max_fff(len_squared_v3(egrid->increment_x),
+ len_squared_v3(egrid->increment_y),
+ len_squared_v3(egrid->increment_z))) + 1.0f);
/* Debug Display */
if (DRW_state_draw_support() &&
(probe->flag & LIGHTPROBE_FLAG_SHOW_DATA))
{
- struct Gwn_Batch *geom = DRW_cache_sphere_get();
- DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.probe_grid_display_sh, psl->probe_display, geom);
- DRW_shgroup_set_instance_count(grp, ped->num_cell);
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_grid_display_sh, psl->probe_display);
DRW_shgroup_uniform_int(grp, "offset", &egrid->offset, 1);
DRW_shgroup_uniform_ivec3(grp, "grid_resolution", egrid->resolution, 1);
DRW_shgroup_uniform_vec3(grp, "corner", egrid->corner, 1);
DRW_shgroup_uniform_vec3(grp, "increment_x", egrid->increment_x, 1);
DRW_shgroup_uniform_vec3(grp, "increment_y", egrid->increment_y, 1);
DRW_shgroup_uniform_vec3(grp, "increment_z", egrid->increment_z, 1);
- DRW_shgroup_uniform_buffer(grp, "irradianceGrid", &sldata->irradiance_pool);
+ DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &sldata->irradiance_pool);
DRW_shgroup_uniform_float(grp, "sphere_size", &probe->data_draw_size, 1);
+ DRW_shgroup_call_instances_add(grp, DRW_cache_sphere_get(), NULL, (unsigned int *)&ped->num_cell);
}
}
}
@@ -844,7 +910,6 @@ static void EEVEE_lightprobes_updates(EEVEE_ViewLayerData *sldata, EEVEE_PassLis
void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
- EEVEE_StorageList *stl = vedata->stl;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
Object *ob;
@@ -852,6 +917,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
/* Free textures if number mismatch. */
if (pinfo->num_cube != pinfo->cache_num_cube) {
DRW_TEXTURE_FREE_SAFE(sldata->probe_pool);
+ pinfo->cache_num_cube = pinfo->num_cube;
}
if (pinfo->num_planar != pinfo->cache_num_planar) {
@@ -875,21 +941,18 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
/* XXX this should be run each frame as it ensure planar_depth is set */
planar_pool_ensure_alloc(vedata, pinfo->num_planar);
- /* Setup planar filtering pass */
- DRW_shgroup_set_instance_count(stl->g_data->planar_downsample, pinfo->num_planar);
-
if (!sldata->probe_pool) {
sldata->probe_pool = DRW_texture_create_2D_array(pinfo->cubemap_res, pinfo->cubemap_res, max_ff(1, pinfo->num_cube),
DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
if (sldata->probe_filter_fb) {
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+ GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
}
-
/* Tag probes to refresh */
- e_data.update_world |= PROBE_UPDATE_CUBE;
- common_data->prb_num_render_cube = 0;
- pinfo->cache_num_cube = pinfo->num_cube;
+ pinfo->update_world |= PROBE_UPDATE_CUBE;
+ }
+ if ((pinfo->update_world & PROBE_UPDATE_CUBE) != 0) {
+ common_data->prb_num_render_cube = 0;
for (int i = 1; (ob = pinfo->probes_cube_ref[i]) && (i < MAX_PROBE); i++) {
EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
ped->need_update = true;
@@ -898,11 +961,6 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
}
}
- DRWFboTexture tex_filter = {&sldata->probe_pool, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
-
- DRW_framebuffer_init(&sldata->probe_filter_fb, &draw_engine_eevee_type, pinfo->cubemap_res, pinfo->cubemap_res, &tex_filter, 1);
-
-
#ifdef IRRADIANCE_SH_L2
/* we need a signed format for Spherical Harmonics */
int irradiance_format = DRW_TEX_RGBA_16;
@@ -919,11 +977,14 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
sldata->irradiance_rt = DRW_texture_create_2D_array(irr_size[0], irr_size[1], irr_size[2],
irradiance_format, DRW_TEX_FILTER, NULL);
}
- common_data->prb_num_render_grid = 0;
- pinfo->updated_bounce = 0;
+ /* Tag probes to refresh */
+ pinfo->update_world |= PROBE_UPDATE_GRID;
pinfo->grid_initialized = false;
- e_data.update_world |= PROBE_UPDATE_GRID;
+ }
+ if ((pinfo->update_world & PROBE_UPDATE_GRID) != 0) {
+ common_data->prb_num_render_grid = 0;
+ pinfo->updated_bounce = 0;
for (int i = 1; (ob = pinfo->probes_grid_ref[i]) && (i < MAX_PROBE); i++) {
EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
ped->need_update = true;
@@ -936,12 +997,12 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
common_data->prb_num_render_grid = pinfo->num_grid;
}
+ EEVEE_planar_reflections_cache_finish(sldata, vedata->stl);
+
EEVEE_lightprobes_updates(sldata, vedata->psl, vedata->stl);
- EEVEE_planar_reflections_updates(sldata, vedata->stl);
DRW_uniformbuffer_update(sldata->probe_ubo, &sldata->probes->probe_data);
DRW_uniformbuffer_update(sldata->grid_ubo, &sldata->probes->grid_data);
- DRW_uniformbuffer_update(sldata->planar_ubo, &sldata->probes->planar_data);
}
static void downsample_planar(void *vedata, int level)
@@ -973,14 +1034,17 @@ static void glossy_filter_probe(
/* Max lod used from the render target probe */
pinfo->lod_rt_max = floorf(log2f(pinfo->target_size)) - 2.0f;
+ /* Start fresh */
+ GPU_framebuffer_ensure_config(&sldata->probe_filter_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_NONE
+ });
+
/* 2 - Let gpu create Mipmaps for Filtered Importance Sampling. */
/* Bind next framebuffer to be able to gen. mips for probe_rt. */
- DRW_framebuffer_bind(sldata->probe_filter_fb);
- EEVEE_downsample_cube_buffer(vedata, sldata->probe_filter_fb, sldata->probe_rt, (int)(pinfo->lod_rt_max));
+ EEVEE_downsample_cube_buffer(vedata, sldata->probe_rt, (int)(pinfo->lod_rt_max));
/* 3 - Render to probe array to the specified layer, do prefiltering. */
- /* Detach to rebind the right mipmap. */
- DRW_framebuffer_texture_detach(sldata->probe_pool);
float mipsize = pinfo->cubemap_res;
const int maxlevel = (int)floorf(log2f(pinfo->cubemap_res));
const int min_lod_level = 3;
@@ -1023,19 +1087,19 @@ static void glossy_filter_probe(
pinfo->invsamples_ct = 1.0f / pinfo->samples_ct;
pinfo->lodfactor = bias + 0.5f * log((float)(pinfo->target_size * pinfo->target_size) * pinfo->invsamples_ct) / log(2);
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, i);
- DRW_framebuffer_viewport_size(sldata->probe_filter_fb, 0, 0, mipsize, mipsize);
+ GPU_framebuffer_ensure_config(&sldata->probe_filter_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE_MIP(sldata->probe_pool, i)
+ });
+ GPU_framebuffer_bind(sldata->probe_filter_fb);
+ GPU_framebuffer_viewport_set(sldata->probe_filter_fb, 0, 0, mipsize, mipsize);
DRW_draw_pass(psl->probe_glossy_compute);
- DRW_framebuffer_texture_detach(sldata->probe_pool);
mipsize /= 2;
CLAMP_MIN(mipsize, 1);
}
/* For shading, save max level of the octahedron map */
sldata->common_data.prb_lod_cube_max = (float)(maxlevel - min_lod_level) - 1.0f;
-
- /* reattach to have a valid framebuffer. */
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
}
/* Diffuse filter probe_rt to irradiance_pool at index probe_idx */
@@ -1078,14 +1142,21 @@ static void diffuse_filter_probe(
pinfo->lod_rt_max = 2.0f; /* Improve cache reuse */
#endif
- /* 4 - Compute spherical harmonics */
- DRW_framebuffer_bind(sldata->probe_filter_fb);
- EEVEE_downsample_cube_buffer(vedata, sldata->probe_filter_fb, sldata->probe_rt, (int)(pinfo->lod_rt_max));
-
- DRW_framebuffer_texture_detach(sldata->probe_pool);
- DRW_framebuffer_texture_layer_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0, 0);
+ /* Start fresh */
+ GPU_framebuffer_ensure_config(&sldata->probe_filter_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_NONE
+ });
- DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, size[0], size[1]);
+ /* 4 - Compute spherical harmonics */
+ EEVEE_downsample_cube_buffer(vedata, sldata->probe_rt, (int)(pinfo->lod_rt_max));
+
+ GPU_framebuffer_ensure_config(&sldata->probe_filter_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE_LAYER(sldata->irradiance_rt, 0)
+ });
+ GPU_framebuffer_bind(sldata->probe_filter_fb);
+ GPU_framebuffer_viewport_set(sldata->probe_filter_fb, x, y, size[0], size[1]);
DRW_draw_pass(psl->probe_diffuse_compute);
/* World irradiance have no visibility */
@@ -1105,18 +1176,16 @@ static void diffuse_filter_probe(
x = common_data->prb_irradiance_vis_size * (offset % cell_per_row);
y = common_data->prb_irradiance_vis_size * ((offset / cell_per_row) % cell_per_col);
int layer = 1 + ((offset / cell_per_row) / cell_per_col);
-
- DRW_framebuffer_texture_detach(sldata->irradiance_rt);
- DRW_framebuffer_texture_layer_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, layer, 0);
-
- DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, common_data->prb_irradiance_vis_size,
- common_data->prb_irradiance_vis_size);
+ const int vis_size = common_data->prb_irradiance_vis_size;
+
+ GPU_framebuffer_ensure_config(&sldata->probe_filter_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE_LAYER(sldata->irradiance_rt, layer)
+ });
+ GPU_framebuffer_bind(sldata->probe_filter_fb);
+ GPU_framebuffer_viewport_set(sldata->probe_filter_fb, x, y, vis_size, vis_size);
DRW_draw_pass(psl->probe_visibility_compute);
}
-
- /* reattach to have a valid framebuffer. */
- DRW_framebuffer_texture_detach(sldata->irradiance_rt);
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
}
/* Render the scene to the probe_rt texture. */
@@ -1126,11 +1195,17 @@ static void render_scene_to_probe(
{
EEVEE_TextureList *txl = vedata->txl;
EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
- float winmat[4][4], wininv[4][4], posmat[4][4];
+ DRWMatrixState matstate;
+ float (*viewmat)[4] = matstate.mat[DRW_MAT_VIEW];
+ float (*viewinv)[4] = matstate.mat[DRW_MAT_VIEWINV];
+ float (*persmat)[4] = matstate.mat[DRW_MAT_PERS];
+ float (*persinv)[4] = matstate.mat[DRW_MAT_PERSINV];
+ float (*winmat)[4] = matstate.mat[DRW_MAT_WIN];
+ float (*wininv)[4] = matstate.mat[DRW_MAT_WININV];
+ float posmat[4][4];
unit_m4(posmat);
/* Move to capture position */
@@ -1145,23 +1220,14 @@ static void render_scene_to_probe(
/* Avoid using the texture attached to framebuffer when rendering. */
/* XXX */
GPUTexture *tmp_planar_pool = txl->planar_pool;
- GPUTexture *tmp_minz = stl->g_data->minzbuffer;
GPUTexture *tmp_maxz = txl->maxzbuffer;
txl->planar_pool = e_data.planar_pool_placeholder;
- stl->g_data->minzbuffer = e_data.depth_placeholder;
txl->maxzbuffer = e_data.depth_placeholder;
/* Update common uniforms */
DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
- /* Detach to rebind the right cubeface. */
- DRW_framebuffer_bind(sldata->probe_fb);
- DRW_framebuffer_texture_detach(sldata->probe_rt);
- DRW_framebuffer_texture_detach(sldata->probe_depth_rt);
for (int i = 0; i < 6; ++i) {
- float viewmat[4][4], persmat[4][4];
- float viewinv[4][4], persinv[4][4];
-
/* Setup custom matrices */
mul_m4_m4m4(viewmat, cubefacemat[i], posmat);
mul_m4_m4m4(persmat, winmat, viewmat);
@@ -1169,21 +1235,13 @@ static void render_scene_to_probe(
invert_m4_m4(viewinv, viewmat);
invert_m4_m4(wininv, winmat);
- DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS);
- DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW);
- DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV);
- DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN);
- DRW_viewport_matrix_override_set(wininv, DRW_MAT_WININV);
+ DRW_viewport_matrix_override_set_all(&matstate);
/* Be sure that cascaded shadow maps are updated. */
EEVEE_draw_shadows(sldata, psl);
- DRW_framebuffer_cubeface_attach(sldata->probe_fb, sldata->probe_rt, 0, i, 0);
- DRW_framebuffer_cubeface_attach(sldata->probe_fb, sldata->probe_depth_rt, 0, i, 0);
- DRW_framebuffer_viewport_size(sldata->probe_fb, 0, 0, pinfo->target_size, pinfo->target_size);
-
- DRW_framebuffer_clear(false, true, false, NULL, 1.0);
+ GPU_framebuffer_bind(sldata->probe_face_fb[i]);
+ GPU_framebuffer_clear_depth(sldata->probe_face_fb[i], 1.0);
/* Depth prepass */
DRW_draw_pass(psl->depth_pass);
@@ -1193,68 +1251,59 @@ static void render_scene_to_probe(
// EEVEE_create_minmax_buffer(vedata, sldata->probe_depth_rt);
- /* Rebind Planar FB */
- DRW_framebuffer_bind(sldata->probe_fb);
+ /* Rebind Target FB */
+ GPU_framebuffer_bind(sldata->probe_face_fb[i]);
/* Shading pass */
EEVEE_draw_default_passes(psl);
DRW_draw_pass(psl->material_pass);
DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
-
- DRW_framebuffer_texture_detach(sldata->probe_rt);
- DRW_framebuffer_texture_detach(sldata->probe_depth_rt);
}
- DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_rt, 0, 0);
- DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_depth_rt, 0, 0);
-
- DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
- DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_unset(DRW_MAT_VIEW);
- DRW_viewport_matrix_override_unset(DRW_MAT_VIEWINV);
- DRW_viewport_matrix_override_unset(DRW_MAT_WIN);
- DRW_viewport_matrix_override_unset(DRW_MAT_WININV);
/* Restore */
txl->planar_pool = tmp_planar_pool;
- stl->g_data->minzbuffer = tmp_minz;
txl->maxzbuffer = tmp_maxz;
}
static void render_scene_to_planar(
EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, int layer,
- float (*viewmat)[4], float (*persmat)[4],
- float clip_plane[4])
+ EEVEE_LightProbeEngineData *ped)
{
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
EEVEE_PassList *psl = vedata->psl;
- float viewinv[4][4];
- float persinv[4][4];
+ float (*viewmat)[4] = ped->mats.mat[DRW_MAT_VIEW];
+ float (*viewinv)[4] = ped->mats.mat[DRW_MAT_VIEWINV];
+ float (*persmat)[4] = ped->mats.mat[DRW_MAT_PERS];
+ float (*persinv)[4] = ped->mats.mat[DRW_MAT_PERSINV];
+ float (*winmat)[4] = ped->mats.mat[DRW_MAT_WIN];
+ float (*wininv)[4] = ped->mats.mat[DRW_MAT_WININV];
invert_m4_m4(viewinv, viewmat);
invert_m4_m4(persinv, persmat);
+ invert_m4_m4(wininv, winmat);
- DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS);
- DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW);
- DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV);
-
- /* Since we are rendering with an inverted view matrix, we need
- * to invert the facing for backface culling to be the same. */
- DRW_state_invert_facing();
+ DRW_viewport_matrix_override_set_all(&ped->mats);
/* Be sure that cascaded shadow maps are updated. */
EEVEE_draw_shadows(sldata, psl);
- DRW_state_clip_planes_add(clip_plane);
+ /* Since we are rendering with an inverted view matrix, we need
+ * to invert the facing for backface culling to be the same. */
+ DRW_state_invert_facing();
+ /* Set clipping plan */
+ copy_v4_v4(sldata->clip_data.clip_planes[0], ped->planer_eq_offset);
+ DRW_uniformbuffer_update(sldata->clip_ubo, &sldata->clip_data);
+ DRW_state_clip_planes_count_set(1);
- /* Attach depth here since it's a DRW_TEX_TEMP */
- DRW_framebuffer_texture_layer_attach(fbl->planarref_fb, txl->planar_depth, 0, layer, 0);
- DRW_framebuffer_texture_layer_attach(fbl->planarref_fb, txl->planar_pool, 0, layer, 0);
- DRW_framebuffer_bind(fbl->planarref_fb);
+ GPU_framebuffer_ensure_config(&fbl->planarref_fb, {
+ GPU_ATTACHMENT_TEXTURE_LAYER(txl->planar_depth, layer),
+ GPU_ATTACHMENT_TEXTURE_LAYER(txl->planar_pool, layer)
+ });
- DRW_framebuffer_clear(false, true, false, NULL, 1.0);
+ GPU_framebuffer_bind(fbl->planarref_fb);
+ GPU_framebuffer_clear_depth(fbl->planarref_fb, 1.0);
/* Avoid using the texture attached to framebuffer when rendering. */
/* XXX */
@@ -1263,9 +1312,14 @@ static void render_scene_to_planar(
txl->planar_pool = e_data.planar_pool_placeholder;
txl->planar_depth = e_data.depth_array_placeholder;
+ /* Slight modification: we handle refraction as normal
+ * shading and don't do SSRefraction. */
+
/* Depth prepass */
DRW_draw_pass(psl->depth_pass_clip);
DRW_draw_pass(psl->depth_pass_clip_cull);
+ DRW_draw_pass(psl->refract_depth_pass);
+ DRW_draw_pass(psl->refract_depth_pass_cull);
/* Background */
DRW_draw_pass(psl->probe_background);
@@ -1276,12 +1330,20 @@ static void render_scene_to_planar(
EEVEE_occlusion_compute(sldata, vedata, tmp_planar_depth, layer);
/* Rebind Planar FB */
- DRW_framebuffer_bind(fbl->planarref_fb);
+ GPU_framebuffer_bind(fbl->planarref_fb);
/* Shading pass */
EEVEE_draw_default_passes(psl);
DRW_draw_pass(psl->material_pass);
DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
+ DRW_draw_pass(psl->refract_pass);
+
+ /* Transparent */
+ if (DRW_state_is_image_render()) {
+ /* Do the reordering only for offline because it can be costly. */
+ DRW_pass_sort_shgroup_z(psl->transparent_pass);
+ }
+ DRW_draw_pass(psl->transparent_pass);
DRW_state_invert_facing();
DRW_state_clip_planes_reset();
@@ -1289,64 +1351,37 @@ static void render_scene_to_planar(
/* Restore */
txl->planar_pool = tmp_planar_pool;
txl->planar_depth = tmp_planar_depth;
- DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
- DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_unset(DRW_MAT_VIEW);
- DRW_viewport_matrix_override_unset(DRW_MAT_VIEWINV);
-
- DRW_framebuffer_texture_detach(txl->planar_pool);
- DRW_framebuffer_texture_detach(txl->planar_depth);
}
static void render_world_to_probe(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
{
EEVEE_LightProbesInfo *pinfo = sldata->probes;
- float winmat[4][4], wininv[4][4];
+ DRWMatrixState matstate;
+ float (*viewmat)[4] = matstate.mat[DRW_MAT_VIEW];
+ float (*viewinv)[4] = matstate.mat[DRW_MAT_VIEWINV];
+ float (*persmat)[4] = matstate.mat[DRW_MAT_PERS];
+ float (*persinv)[4] = matstate.mat[DRW_MAT_PERSINV];
+ float (*winmat)[4] = matstate.mat[DRW_MAT_WIN];
+ float (*wininv)[4] = matstate.mat[DRW_MAT_WININV];
- /* 1 - Render to cubemap target using geometry shader. */
/* For world probe, we don't need to clear since we render the background directly. */
pinfo->layer = 0;
perspective_m4(winmat, -0.1f, 0.1f, -0.1f, 0.1f, 0.1f, 1.0f);
invert_m4_m4(wininv, winmat);
- /* Detach to rebind the right cubeface. */
- DRW_framebuffer_bind(sldata->probe_fb);
- DRW_framebuffer_texture_detach(sldata->probe_rt);
- DRW_framebuffer_texture_detach(sldata->probe_depth_rt);
for (int i = 0; i < 6; ++i) {
- float viewmat[4][4], persmat[4][4];
- float viewinv[4][4], persinv[4][4];
-
- DRW_framebuffer_cubeface_attach(sldata->probe_fb, sldata->probe_rt, 0, i, 0);
- DRW_framebuffer_viewport_size(sldata->probe_fb, 0, 0, pinfo->target_size, pinfo->target_size);
-
/* Setup custom matrices */
copy_m4_m4(viewmat, cubefacemat[i]);
mul_m4_m4m4(persmat, winmat, viewmat);
invert_m4_m4(persinv, persmat);
invert_m4_m4(viewinv, viewmat);
+ DRW_viewport_matrix_override_set_all(&matstate);
- DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS);
- DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW);
- DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV);
- DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN);
- DRW_viewport_matrix_override_set(wininv, DRW_MAT_WININV);
-
+ GPU_framebuffer_bind(sldata->probe_face_fb[i]);
+ GPU_framebuffer_clear_depth(sldata->probe_face_fb[i], 1.0f);
DRW_draw_pass(psl->probe_background);
-
- DRW_framebuffer_texture_detach(sldata->probe_rt);
}
- DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_rt, 0, 0);
- DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_depth_rt, 0, 0);
-
- DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
- DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_unset(DRW_MAT_VIEW);
- DRW_viewport_matrix_override_unset(DRW_MAT_VIEWINV);
- DRW_viewport_matrix_override_unset(DRW_MAT_WIN);
- DRW_viewport_matrix_override_unset(DRW_MAT_WININV);
}
static void lightprobe_cell_grid_location_get(EEVEE_LightGrid *egrid, int cell_idx, float r_local_cell[3])
@@ -1373,25 +1408,39 @@ static void lightprobe_cell_world_location_get(EEVEE_LightGrid *egrid, float loc
static void lightprobes_refresh_world(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ DRWMatrixState saved_mats;
+
+ /* We need to save the Matrices before overidding them */
+ DRW_viewport_matrix_get_all(&saved_mats);
render_world_to_probe(sldata, psl);
- if (e_data.update_world & PROBE_UPDATE_CUBE) {
+ if (pinfo->update_world & PROBE_UPDATE_CUBE) {
glossy_filter_probe(sldata, vedata, psl, 0, 1.0);
common_data->prb_num_render_cube = 1;
}
- if (e_data.update_world & PROBE_UPDATE_GRID) {
+ if (pinfo->update_world & PROBE_UPDATE_GRID) {
diffuse_filter_probe(sldata, vedata, psl, 0, 0.0, 0.0, 0.0, 0.0, 1.0);
+
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
- DRW_framebuffer_texture_detach(sldata->probe_pool);
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+
+ GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+ GPU_framebuffer_bind(sldata->probe_filter_fb);
DRW_draw_pass(psl->probe_grid_fill);
- DRW_framebuffer_texture_detach(sldata->irradiance_rt);
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+
common_data->prb_num_render_grid = 1;
+ /* Reset volume history. */
+ stl->effects->volume_current_sample = -1;
+ common_data->vol_history_alpha = 0.0f;
}
- e_data.update_world = 0;
+ pinfo->update_world = 0;
DRW_viewport_request_redraw();
+ /* Do not let this frame accumulate. */
+ stl->effects->taa_current_sample = 1;
+
+ DRW_viewport_matrix_override_set_all(&saved_mats);
}
static void lightprobes_refresh_initialize_grid(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
@@ -1402,39 +1451,47 @@ static void lightprobes_refresh_initialize_grid(EEVEE_ViewLayerData *sldata, EEV
/* Grid is already initialized, nothing to do. */
return;
}
- DRW_framebuffer_texture_detach(sldata->probe_pool);
/* Flood fill with world irradiance. */
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
- DRW_framebuffer_bind(sldata->probe_filter_fb);
+ GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+ GPU_framebuffer_bind(sldata->probe_filter_fb);
DRW_draw_pass(psl->probe_grid_fill);
- DRW_framebuffer_texture_detach(sldata->irradiance_rt);
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+
+ GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+ GPU_framebuffer_bind(sldata->probe_filter_fb);
DRW_draw_pass(psl->probe_grid_fill);
- DRW_framebuffer_texture_detach(sldata->irradiance_rt);
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
- /* Reattach to have a valid framebuffer. */
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+
pinfo->grid_initialized = true;
}
-static void lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
Object *ob;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ DRWMatrixState saved_mats;
if (pinfo->num_planar == 0) {
+ /* Disable SSR if we cannot read previous frame */
+ common_data->ssr_toggle = vedata->stl->g_data->valid_double_buffer;
+ common_data->prb_num_planar = 0;
return;
}
+ EEVEE_planar_reflections_updates(sldata);
+ DRW_uniformbuffer_update(sldata->planar_ubo, &sldata->probes->planar_data);
+
+ /* We need to save the Matrices before overidding them */
+ DRW_viewport_matrix_get_all(&saved_mats);
+
/* Temporary Remove all planar reflections (avoid lag effect). */
common_data->prb_num_planar = 0;
/* Turn off ssr to avoid black specular */
- /* TODO : Enable SSR in planar reflections? (Would be very heavy) */
common_data->ssr_toggle = false;
common_data->sss_toggle = false;
@@ -1442,12 +1499,7 @@ static void lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *
for (int i = 0; (ob = pinfo->probes_planar_ref[i]) && (i < MAX_PLANAR); i++) {
EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
- if (!ped->need_update) {
- continue;
- }
- render_scene_to_planar(sldata, vedata, i, ped->viewmat, ped->persmat, ped->planer_eq_offset);
- ped->need_update = false;
- ped->probe_id = i;
+ render_scene_to_planar(sldata, vedata, i, ped);
}
/* Restore */
@@ -1455,15 +1507,30 @@ static void lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *
common_data->ssr_toggle = true;
common_data->sss_toggle = true;
- /* If there is at least one planar probe */
- if (pinfo->num_planar > 0 && (vedata->stl->effects->enabled_effects & EFFECT_SSR) != 0) {
+ /* Prefilter for SSR */
+ if ((vedata->stl->effects->enabled_effects & EFFECT_SSR) != 0) {
const int max_lod = 9;
DRW_stats_group_start("Planar Probe Downsample");
- DRW_framebuffer_recursive_downsample(vedata->fbl->downsample_fb, txl->planar_pool, max_lod, &downsample_planar, vedata);
+
+ GPU_framebuffer_ensure_config(&fbl->planar_downsample_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->planar_pool)
+ });
+ GPU_framebuffer_recursive_downsample(fbl->planar_downsample_fb, max_lod, &downsample_planar, vedata);
/* For shading, save max level of the planar map */
common_data->prb_lod_planar_max = (float)(max_lod);
DRW_stats_group_end();
}
+
+ DRW_viewport_matrix_override_set_all(&saved_mats);
+
+ if (DRW_state_is_image_render()) {
+ /* Sort transparents because planar reflections could have re-sorted them. */
+ DRW_pass_sort_shgroup_z(vedata->psl->transparent_pass);
+ }
+
+ /* Disable SSR if we cannot read previous frame */
+ common_data->ssr_toggle = vedata->stl->g_data->valid_double_buffer;
}
static void lightprobes_refresh_cube(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
@@ -1493,10 +1560,11 @@ static void lightprobes_refresh_cube(EEVEE_ViewLayerData *sldata, EEVEE_Data *ve
DRW_viewport_request_redraw();
/* Do not let this frame accumulate. */
stl->effects->taa_current_sample = 1;
-
/* Only do one probe per frame */
return;
}
+
+ pinfo->do_cube_update = false;
}
static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
@@ -1516,6 +1584,9 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
return;
}
}
+ /* We need to save the Matrices before overidding them */
+ DRWMatrixState saved_mats;
+ DRW_viewport_matrix_get_all(&saved_mats);
/* Make sure grid is initialized. */
lightprobes_refresh_initialize_grid(sldata, vedata);
/* Reflection probes depend on diffuse lighting thus on irradiance grid,
@@ -1615,6 +1686,11 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
DRW_viewport_request_redraw();
/* Do not let this frame accumulate. */
stl->effects->taa_current_sample = 1;
+ /* Reset volume history. */
+ stl->effects->volume_current_sample = -1;
+ common_data->vol_history_alpha = 0.0f;
+ /* Restore matrices */
+ DRW_viewport_matrix_override_set_all(&saved_mats);
return;
}
@@ -1631,25 +1707,36 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
}
/* Reset the next buffer so we can see the progress. */
/* irradiance_rt is already the next rt because of the previous SWAP */
- DRW_framebuffer_texture_detach(sldata->probe_pool);
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
- DRW_framebuffer_bind(sldata->probe_filter_fb);
+ GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+ GPU_framebuffer_bind(sldata->probe_filter_fb);
DRW_draw_pass(psl->probe_grid_fill);
- DRW_framebuffer_texture_detach(sldata->irradiance_rt);
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+
+ GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
/* Swap AFTER */
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
}
}
/* Refresh cube probe when needed. */
lightprobes_refresh_cube(sldata, vedata);
+ /* Restore matrices */
+ DRW_viewport_matrix_override_set_all(&saved_mats);
}
-void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+bool EEVEE_lightprobes_all_probes_ready(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(vedata))
{
EEVEE_LightProbesInfo *pinfo = sldata->probes;
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
+ return ((pinfo->do_cube_update == false) &&
+ (pinfo->updated_bounce == pinfo->num_bounce) &&
+ (common_data->prb_num_render_cube == pinfo->num_cube));
+}
+
+void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+
/* Disable specular lighting when rendering probes to avoid feedback loops (looks bad). */
common_data->spec_toggle = false;
common_data->ssr_toggle = false;
@@ -1662,10 +1749,10 @@ void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
common_data->ao_dist = 0.0f;
/* Render world in priority */
- if (e_data.update_world) {
+ if (pinfo->update_world) {
lightprobes_refresh_world(sldata, vedata);
}
- else if (pinfo->do_cube_update || (pinfo->updated_bounce < pinfo->num_bounce)) {
+ else if (EEVEE_lightprobes_all_probes_ready(sldata, vedata) == false && pinfo->all_materials_updated) {
lightprobes_refresh_all_no_world(sldata, vedata);
}
@@ -1675,15 +1762,12 @@ void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
common_data->sss_toggle = true;
common_data->ao_dist = tmp_ao_dist;
common_data->ao_settings = tmp_ao_settings;
-
- lightprobes_refresh_planar(sldata, vedata);
-
- /* Disable SSR if we cannot read previous frame */
- common_data->ssr_toggle = vedata->stl->g_data->valid_double_buffer;
}
void EEVEE_lightprobes_free(void)
{
+ MEM_SAFE_FREE(e_data.format_probe_display_cube);
+ MEM_SAFE_FREE(e_data.format_probe_display_planar);
DRW_SHADER_FREE_SAFE(e_data.probe_default_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_glossy_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_diffuse_sh);
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index 69b58bf9670..7496142a26e 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -26,6 +26,7 @@
#include "DRW_render.h"
#include "BLI_dynstr.h"
+#include "BLI_rect.h"
#include "BKE_object.h"
@@ -106,50 +107,6 @@ void EEVEE_lights_init(EEVEE_ViewLayerData *sldata)
if (!e_data.shadow_sh) {
e_data.shadow_sh = DRW_shader_create(
datatoc_shadow_vert_glsl, datatoc_shadow_geom_glsl, datatoc_shadow_frag_glsl, NULL);
-
- DynStr *ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, datatoc_concentric_samples_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_shadow_store_frag_glsl);
- char *store_shadow_shader_str = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
-
- e_data.shadow_store_cube_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
- store_shadow_shader_str,
- "#define ESM\n");
- e_data.shadow_store_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
- store_shadow_shader_str,
- "#define ESM\n"
- "#define CSM\n");
-
- e_data.shadow_store_cube_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
- store_shadow_shader_str,
- "#define VSM\n");
- e_data.shadow_store_cascade_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
- store_shadow_shader_str,
- "#define VSM\n"
- "#define CSM\n");
-
- MEM_freeN(store_shadow_shader_str);
-
- e_data.shadow_copy_cube_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
- datatoc_shadow_copy_frag_glsl,
- "#define ESM\n"
- "#define COPY\n");
- e_data.shadow_copy_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
- datatoc_shadow_copy_frag_glsl,
- "#define ESM\n"
- "#define COPY\n"
- "#define CSM\n");
-
- e_data.shadow_copy_cube_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
- datatoc_shadow_copy_frag_glsl,
- "#define VSM\n"
- "#define COPY\n");
- e_data.shadow_copy_cascade_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
- datatoc_shadow_copy_frag_glsl,
- "#define VSM\n"
- "#define COPY\n"
- "#define CSM\n");
}
if (!sldata->lamps) {
@@ -203,11 +160,67 @@ void EEVEE_lights_init(EEVEE_ViewLayerData *sldata)
linfo->shadow_cube_target_size = new_cube_target_size;
linfo->shadow_render_data.cube_texel_size = 1.0 / (float)linfo->shadow_cube_target_size;
}
+
+ /* only compile the ones needed. reduce startup time. */
+ if ((sh_method == SHADOW_ESM) && !e_data.shadow_store_cube_sh[SHADOW_ESM]) {
+ DynStr *ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_concentric_samples_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_shadow_store_frag_glsl);
+ char *store_shadow_shader_str = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ e_data.shadow_store_cube_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
+ store_shadow_shader_str,
+ "#define ESM\n");
+ e_data.shadow_store_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
+ store_shadow_shader_str,
+ "#define ESM\n"
+ "#define CSM\n");
+ MEM_freeN(store_shadow_shader_str);
+
+ e_data.shadow_copy_cube_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
+ datatoc_shadow_copy_frag_glsl,
+ "#define ESM\n"
+ "#define COPY\n");
+ e_data.shadow_copy_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
+ datatoc_shadow_copy_frag_glsl,
+ "#define ESM\n"
+ "#define COPY\n"
+ "#define CSM\n");
+ }
+ else if ((sh_method == SHADOW_VSM) && !e_data.shadow_store_cube_sh[SHADOW_VSM]) {
+ DynStr *ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_concentric_samples_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_shadow_store_frag_glsl);
+ char *store_shadow_shader_str = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ e_data.shadow_store_cube_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
+ store_shadow_shader_str,
+ "#define VSM\n");
+ e_data.shadow_store_cascade_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
+ store_shadow_shader_str,
+ "#define VSM\n"
+ "#define CSM\n");
+ MEM_freeN(store_shadow_shader_str);
+
+ e_data.shadow_copy_cube_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
+ datatoc_shadow_copy_frag_glsl,
+ "#define VSM\n"
+ "#define COPY\n");
+ e_data.shadow_copy_cascade_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
+ datatoc_shadow_copy_frag_glsl,
+ "#define VSM\n"
+ "#define COPY\n"
+ "#define CSM\n");
+ }
}
-void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
+void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_LampsInfo *linfo = sldata->lamps;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_PassList *psl = vedata->psl;
linfo->shcaster_frontbuffer->count = 0;
linfo->num_light = 0;
@@ -228,7 +241,7 @@ void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
DRWShadingGroup *grp = DRW_shgroup_create(
e_data.shadow_store_cube_sh[linfo->shadow_method], psl->shadow_cube_store_pass);
- DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cube_blur);
+ DRW_shgroup_uniform_texture_ref(grp, "shadowTexture", &sldata->shadow_cube_blur);
DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
@@ -239,7 +252,7 @@ void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
DRWShadingGroup *grp = DRW_shgroup_create(
e_data.shadow_store_cascade_sh[linfo->shadow_method], psl->shadow_cascade_store_pass);
- DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cascade_blur);
+ DRW_shgroup_uniform_texture_ref(grp, "shadowTexture", &sldata->shadow_cascade_blur);
DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
DRW_shgroup_uniform_int(grp, "cascadeId", &linfo->current_shadow_cascade, 1);
DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
@@ -251,7 +264,7 @@ void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
DRWShadingGroup *grp = DRW_shgroup_create(
e_data.shadow_copy_cube_sh[linfo->shadow_method], psl->shadow_cube_copy_pass);
- DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cube_target);
+ DRW_shgroup_uniform_texture_ref(grp, "shadowTexture", &sldata->shadow_cube_target);
DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
DRW_shgroup_uniform_int(grp, "faceId", &linfo->current_shadow_face, 1);
@@ -263,7 +276,7 @@ void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
DRWShadingGroup *grp = DRW_shgroup_create(
e_data.shadow_copy_cascade_sh[linfo->shadow_method], psl->shadow_cascade_copy_pass);
- DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cascade_target);
+ DRW_shgroup_uniform_texture_ref(grp, "shadowTexture", &sldata->shadow_cascade_target);
DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
DRW_shgroup_uniform_int(grp, "cascadeId", &linfo->current_shadow_cascade, 1);
@@ -271,15 +284,11 @@ void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
}
{
- psl->shadow_cube_pass = DRW_pass_create(
- "Shadow Cube Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
- }
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+ psl->shadow_pass = DRW_pass_create("Shadow Pass", state);
- {
- psl->shadow_cascade_pass = DRW_pass_create(
- "Shadow Cascade Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ DRWShadingGroup *grp = stl->g_data->shadow_shgrp = DRW_shgroup_create(e_data.shadow_sh, psl->shadow_pass);
+ DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
}
}
@@ -343,7 +352,7 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
/* For light update tracking. */
if ((prev_cube_sh_id >= 0) &&
- (prev_cube_sh_id < linfo->shcaster_backbuffer->count))
+ (prev_cube_sh_id < linfo->shcaster_backbuffer->count))
{
linfo->new_shadow_id[prev_cube_sh_id] = linfo->cpu_cube_ct;
}
@@ -378,24 +387,20 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
/* Add a shadow caster to the shadowpasses */
void EEVEE_lights_cache_shcaster_add(
- EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl, struct Gwn_Batch *geom, float (*obmat)[4])
+ EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, struct Gwn_Batch *geom, Object *ob)
{
- DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.shadow_sh, psl->shadow_cube_pass, geom);
- DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
- DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
- DRW_shgroup_set_instance_count(grp, 6);
-
- grp = DRW_shgroup_instance_create(e_data.shadow_sh, psl->shadow_cascade_pass, geom);
- DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
- DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
- DRW_shgroup_set_instance_count(grp, MAX_CASCADE_NUM);
+ DRW_shgroup_call_object_instances_add(
+ stl->g_data->shadow_shgrp,
+ geom, ob,
+ &sldata->lamps->shadow_instance_count);
}
void EEVEE_lights_cache_shcaster_material_add(
EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl, struct GPUMaterial *gpumat,
struct Gwn_Batch *geom, struct Object *ob, float (*obmat)[4], float *alpha_threshold)
{
- DRWShadingGroup *grp = DRW_shgroup_material_instance_create(gpumat, psl->shadow_cube_pass, geom, ob);
+ /* TODO / PERF : reuse the same shading group for objects with the same material */
+ DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, psl->shadow_pass);
if (grp == NULL) return;
@@ -405,16 +410,7 @@ void EEVEE_lights_cache_shcaster_material_add(
if (alpha_threshold != NULL)
DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1);
- DRW_shgroup_set_instance_count(grp, 6);
-
- grp = DRW_shgroup_material_instance_create(gpumat, psl->shadow_cascade_pass, geom, ob);
- DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
- DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
-
- if (alpha_threshold != NULL)
- DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1);
-
- DRW_shgroup_set_instance_count(grp, MAX_CASCADE_NUM);
+ DRW_shgroup_call_object_instances_add(grp, geom, ob, &sldata->lamps->shadow_instance_count);
}
/* Make that object update shadow casting lamps inside its influence bounding box. */
@@ -519,7 +515,6 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata)
linfo->shadow_size, linfo->shadow_size, MAX_CASCADE_NUM, shadow_pool_format, DRW_TEX_FILTER, NULL);
}
- /* Initialize Textures Array first so DRW_framebuffer_init just bind them. */
if (!sldata->shadow_pool) {
/* All shadows fit in this array */
sldata->shadow_pool = DRW_texture_create_2D_array(
@@ -528,19 +523,18 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata)
}
/* Render FB */
- DRWFboTexture tex_cascade = {&sldata->shadow_cube_target, DRW_TEX_DEPTH_24, 0};
- DRW_framebuffer_init(&sldata->shadow_target_fb, &draw_engine_eevee_type,
- linfo->shadow_size, linfo->shadow_size,
- &tex_cascade, 1);
+ GPU_framebuffer_ensure_config(&sldata->shadow_cube_target_fb, {
+ GPU_ATTACHMENT_TEXTURE(sldata->shadow_cube_target)
+ });
+ GPU_framebuffer_ensure_config(&sldata->shadow_cascade_target_fb, {
+ GPU_ATTACHMENT_TEXTURE(sldata->shadow_cascade_target)
+ });
/* Storage FB */
- DRWFboTexture tex_pool = {&sldata->shadow_pool, shadow_pool_format, DRW_TEX_FILTER};
- DRW_framebuffer_init(&sldata->shadow_store_fb, &draw_engine_eevee_type,
- linfo->shadow_size, linfo->shadow_size,
- &tex_pool, 1);
-
- /* Restore */
- DRW_framebuffer_texture_detach(sldata->shadow_cube_target);
+ GPU_framebuffer_ensure_config(&sldata->shadow_store_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(sldata->shadow_pool)
+ });
/* Update Lamps UBOs. */
EEVEE_lights_update(sldata);
@@ -653,9 +647,15 @@ static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_La
#define LERP(t, a, b) ((a) + (t) * ((b) - (a)))
-static void frustum_min_bounding_sphere(const float corners[8][4], float r_center[3], float *r_radius)
+static double round_to_digits(double value, int digits)
{
-#if 0 /* Simple solution but waist too much space. */
+ double factor = pow(10.0, digits - ceil(log10(fabs(value))));
+ return round(value * factor) / factor;
+}
+
+static void frustum_min_bounding_sphere(const float corners[8][3], float r_center[3], float *r_radius)
+{
+#if 0 /* Simple solution but waste too much space. */
float minvec[3], maxvec[3];
/* compute the bounding box */
@@ -669,19 +669,27 @@ static void frustum_min_bounding_sphere(const float corners[8][4], float r_cente
add_v3_v3v3(r_center, minvec, maxvec);
mul_v3_fl(r_center, 0.5f);
#else
- /* Make the bouding sphere always centered on the front diagonal */
- add_v3_v3v3(r_center, corners[4], corners[7]);
- mul_v3_fl(r_center, 0.5f);
- *r_radius = len_v3v3(corners[0], r_center);
+ /* Find averaged center. */
+ zero_v3(r_center);
+ for (int i = 0; i < 8; ++i) {
+ add_v3_v3(r_center, corners[i]);
+ }
+ mul_v3_fl(r_center, 1.0f / 8.0f);
- /* Search the largest distance between the sphere center
- * and the front plane corners. */
- for (int i = 0; i < 4; ++i) {
- float rad = len_v3v3(corners[4 + i], r_center);
+ /* Search the largest distance from the sphere center. */
+ *r_radius = 0.0f;
+ for (int i = 0; i < 8; ++i) {
+ float rad = len_squared_v3v3(corners[i], r_center);
if (rad > *r_radius) {
*r_radius = rad;
}
}
+
+ /* TODO try to reduce the radius further by moving the center.
+ * Remember we need a __stable__ solution! */
+
+ /* Try to reduce float imprecision leading to shimmering. */
+ *r_radius = (float)round_to_digits(sqrtf(*r_radius), 3);
#endif
}
@@ -711,7 +719,7 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE
}
/* Lamps Matrices */
- float viewmat[4][4], projmat[4][4];
+ float (*viewmat)[4], projmat[4][4];
int sh_nbr = 1; /* TODO : MSM */
int cascade_nbr = la->cascade_count;
@@ -720,6 +728,13 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE
EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id;
EEVEE_ShadowCascade *cascade_data = linfo->shadow_cascade_data + sh_data->cascade_id;
+ /* obmat = Object Space > World Space */
+ /* viewmat = World Space > View Space */
+ invert_m4_m4(sh_data->clipmat.mat[DRW_MAT_VIEW], ob->obmat);
+ viewmat = sh_data->clipmat.mat[DRW_MAT_VIEW];
+ normalize_m4(viewmat);
+ invert_m4_m4(sh_data->clipmat.mat[DRW_MAT_VIEWINV], viewmat);
+
/* The technique consists into splitting
* the view frustum into several sub-frustum
* that are individually receiving one shadow map */
@@ -818,50 +833,41 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE
cascade_data->split_start[0] = LERP(la->cascade_fade, cascade_data->split_end[cascade_nbr - 1], prev_split);
/* For each cascade */
+ rctf rect_clip, rect_cascade;
for (int c = 0; c < cascade_nbr; ++c) {
/* Given 8 frustum corners */
- float corners[8][4] = {
+ float corners[8][3] = {
/* Near Cap */
- {-1.0f, -1.0f, splits_start_ndc[c], 1.0f},
- { 1.0f, -1.0f, splits_start_ndc[c], 1.0f},
- {-1.0f, 1.0f, splits_start_ndc[c], 1.0f},
- { 1.0f, 1.0f, splits_start_ndc[c], 1.0f},
+ {-1.0f, -1.0f, splits_start_ndc[c]},
+ { 1.0f, -1.0f, splits_start_ndc[c]},
+ {-1.0f, 1.0f, splits_start_ndc[c]},
+ { 1.0f, 1.0f, splits_start_ndc[c]},
/* Far Cap */
- {-1.0f, -1.0f, splits_end_ndc[c], 1.0f},
- { 1.0f, -1.0f, splits_end_ndc[c], 1.0f},
- {-1.0f, 1.0f, splits_end_ndc[c], 1.0f},
- { 1.0f, 1.0f, splits_end_ndc[c], 1.0f}
+ {-1.0f, -1.0f, splits_end_ndc[c]},
+ { 1.0f, -1.0f, splits_end_ndc[c]},
+ {-1.0f, 1.0f, splits_end_ndc[c]},
+ { 1.0f, 1.0f, splits_end_ndc[c]}
};
/* Transform them into world space */
for (int i = 0; i < 8; ++i) {
- mul_m4_v4(persinv, corners[i]);
- mul_v3_fl(corners[i], 1.0f / corners[i][3]);
- corners[i][3] = 1.0f;
- }
-
-
- /* Project them into light space */
- invert_m4_m4(viewmat, ob->obmat);
- normalize_v3(viewmat[0]);
- normalize_v3(viewmat[1]);
- normalize_v3(viewmat[2]);
-
- for (int i = 0; i < 8; ++i) {
- mul_m4_v4(viewmat, corners[i]);
+ mul_project_m4_v3(persinv, corners[i]);
}
float center[3];
frustum_min_bounding_sphere(corners, center, &(sh_data->radius[c]));
+ /* Project into lightspace */
+ mul_mat3_m4_v3(viewmat, center);
+
/* Snap projection center to nearest texel to cancel shimmering. */
float shadow_origin[2], shadow_texco[2];
/* Light to texture space. */
mul_v2_v2fl(shadow_origin, center, linfo->shadow_size / (2.0f * sh_data->radius[c]));
/* Find the nearest texel. */
- shadow_texco[0] = round(shadow_origin[0]);
- shadow_texco[1] = round(shadow_origin[1]);
+ shadow_texco[0] = roundf(shadow_origin[0]);
+ shadow_texco[1] = roundf(shadow_origin[1]);
/* Compute offset. */
sub_v2_v2(shadow_texco, shadow_origin);
@@ -871,17 +877,32 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE
add_v2_v2(center, shadow_texco);
/* Expand the projection to cover frustum range */
+ BLI_rctf_init_pt_radius(&rect_cascade, center, sh_data->radius[c]);
orthographic_m4(projmat,
- center[0] - sh_data->radius[c],
- center[0] + sh_data->radius[c],
- center[1] - sh_data->radius[c],
- center[1] + sh_data->radius[c],
+ rect_cascade.xmin, rect_cascade.xmax,
+ rect_cascade.ymin, rect_cascade.ymax,
la->clipsta, la->clipend);
+ if (c == 0) {
+ memcpy(&rect_clip, &rect_cascade, sizeof(rect_clip));
+ }
+ else {
+ BLI_rctf_union(&rect_clip, &rect_cascade);
+ }
+
mul_m4_m4m4(sh_data->viewprojmat[c], projmat, viewmat);
mul_m4_m4m4(cascade_data->shadowmat[c], texcomat, sh_data->viewprojmat[c]);
}
+ /* Clipping mats */
+ orthographic_m4(sh_data->clipmat.mat[DRW_MAT_WIN],
+ rect_clip.xmin, rect_clip.xmax,
+ rect_clip.ymin, rect_clip.ymax,
+ la->clipsta, la->clipend);
+ mul_m4_m4m4(sh_data->clipmat.mat[DRW_MAT_PERS], sh_data->clipmat.mat[DRW_MAT_WIN], viewmat);
+ invert_m4_m4(sh_data->clipmat.mat[DRW_MAT_WININV], sh_data->clipmat.mat[DRW_MAT_WIN]);
+ invert_m4_m4(sh_data->clipmat.mat[DRW_MAT_PERSINV], sh_data->clipmat.mat[DRW_MAT_PERS]);
+
ubo_data->bias = 0.05f * la->bias;
ubo_data->near = la->clipsta;
ubo_data->far = la->clipend;
@@ -983,25 +1004,56 @@ void EEVEE_lights_update(EEVEE_ViewLayerData *sldata)
}
}
+static void eevee_shadows_cube_culling_frustum(EEVEE_ShadowRender *srd)
+{
+ float persmat[4][4], persinv[4][4];
+ float viewmat[4][4], viewinv[4][4];
+ float winmat[4][4], wininv[4][4];
+ orthographic_m4(winmat, -srd->clip_far, srd->clip_far, -srd->clip_far, srd->clip_far, -srd->clip_far, srd->clip_far);
+ DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN);
+
+ invert_m4_m4(wininv, winmat);
+ DRW_viewport_matrix_override_set(wininv, DRW_MAT_WININV);
+
+ unit_m4(viewmat);
+ negate_v3_v3(viewmat[3], srd->position);
+ DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW);
+
+ unit_m4(viewinv);
+ copy_v3_v3(viewinv[3], srd->position);
+ DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV);
+
+ mul_m4_m4m4(persmat, winmat, viewmat);
+ DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS);
+
+ invert_m4_m4(persinv, persmat);
+ DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV);
+}
+
+static void eevee_shadows_cascade_culling_frustum(EEVEE_ShadowCascadeData *evscd)
+{
+ DRW_viewport_matrix_override_set_all(&evscd->clipmat);
+}
+
/* this refresh lamps shadow buffers */
void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
{
EEVEE_LampsInfo *linfo = sldata->lamps;
Object *ob;
int i;
- float clear_col[4] = {FLT_MAX};
+
+ DRWMatrixState saved_mats;
+
+ /* We need to save the Matrices before overidding them */
+ DRW_viewport_matrix_get_all(&saved_mats);
/* Cube Shadow Maps */
DRW_stats_group_start("Cube Shadow Maps");
- DRW_framebuffer_texture_attach(sldata->shadow_target_fb, sldata->shadow_cube_target, 0, 0);
/* Render each shadow to one layer of the array */
for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
Lamp *la = (Lamp *)ob->data;
- float cube_projmat[4][4];
- perspective_m4(cube_projmat, -la->clipsta, la->clipsta, -la->clipsta, la->clipsta, la->clipsta, la->clipend);
-
if (!led->need_update) {
continue;
}
@@ -1009,25 +1061,29 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
EEVEE_ShadowCubeData *evscd = &led->data.scd;
+ float cube_projmat[4][4];
+ float cube_viewmat[4][4];
+ perspective_m4(cube_projmat, -la->clipsta, la->clipsta, -la->clipsta, la->clipsta, la->clipsta, la->clipend);
+ unit_m4(cube_viewmat);
+
srd->clip_near = la->clipsta;
srd->clip_far = la->clipend;
copy_v3_v3(srd->position, ob->obmat[3]);
- for (int j = 0; j < 6; j++) {
- float tmp[4][4];
-
- unit_m4(tmp);
- negate_v3_v3(tmp[3], ob->obmat[3]);
- mul_m4_m4m4(srd->viewmat[j], cubefacemat[j], tmp);
+ negate_v3_v3(cube_viewmat[3], srd->position);
+ for (int j = 0; j < 6; j++) {
+ mul_m4_m4m4(srd->viewmat[j], cubefacemat[j], cube_viewmat);
mul_m4_m4m4(srd->shadowmat[j], cube_projmat, srd->viewmat[j]);
}
DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd);
- DRW_framebuffer_bind(sldata->shadow_target_fb);
- DRW_framebuffer_clear(true, true, false, clear_col, 1.0f);
+ eevee_shadows_cube_culling_frustum(srd);
/* Render shadow cube */
- DRW_draw_pass(psl->shadow_cube_pass);
+ linfo->shadow_instance_count = 6;
+ GPU_framebuffer_bind(sldata->shadow_cube_target_fb);
+ GPU_framebuffer_clear_depth(sldata->shadow_cube_target_fb, 1.0f);
+ DRW_draw_pass(psl->shadow_pass);
/* 0.001f is arbitrary, but it should be relatively small so that filter size is not too big. */
float filter_texture_size = la->soft * 0.001f;
@@ -1040,10 +1096,10 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
linfo->current_shadow_face++)
{
/* Copy using a small 3x3 box filter */
- DRW_framebuffer_cubeface_attach(sldata->shadow_store_fb, sldata->shadow_cube_blur, 0, linfo->current_shadow_face, 0);
- DRW_framebuffer_bind(sldata->shadow_store_fb);
+ GPU_framebuffer_texture_cubeface_attach(sldata->shadow_store_fb, sldata->shadow_cube_blur, 0,
+ linfo->current_shadow_face, 0);
+ GPU_framebuffer_bind(sldata->shadow_store_fb);
DRW_draw_pass(psl->shadow_cube_copy_pass);
- DRW_framebuffer_texture_detach(sldata->shadow_cube_blur);
}
/* Push it to shadowmap array */
@@ -1067,20 +1123,19 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
srd->shadow_inv_samples_ct = 1.0f / (float)srd->shadow_samples_ct;
DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd);
- DRW_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, evscd->layer_id, 0);
- DRW_framebuffer_bind(sldata->shadow_store_fb);
+ GPU_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, evscd->layer_id, 0);
+ GPU_framebuffer_bind(sldata->shadow_store_fb);
DRW_draw_pass(psl->shadow_cube_store_pass);
led->need_update = false;
}
linfo->update_flag &= ~LIGHT_UPDATE_SHADOW_CUBE;
-
- DRW_framebuffer_texture_detach(sldata->shadow_cube_target);
DRW_stats_group_end();
+ DRW_viewport_matrix_override_set_all(&saved_mats);
+
/* Cascaded Shadow Maps */
DRW_stats_group_start("Cascaded Shadow Maps");
- DRW_framebuffer_texture_attach(sldata->shadow_target_fb, sldata->shadow_cascade_target, 0, 0);
for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) {
EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
Lamp *la = (Lamp *)ob->data;
@@ -1097,11 +1152,13 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
}
DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data);
- DRW_framebuffer_bind(sldata->shadow_target_fb);
- DRW_framebuffer_clear(false, true, false, NULL, 1.0);
+ eevee_shadows_cascade_culling_frustum(evscd);
/* Render shadow cascades */
- DRW_draw_pass(psl->shadow_cascade_pass);
+ linfo->shadow_instance_count = la->cascade_count;
+ GPU_framebuffer_bind(sldata->shadow_cascade_target_fb);
+ GPU_framebuffer_clear_depth(sldata->shadow_cascade_target_fb, 1.0);
+ DRW_draw_pass(psl->shadow_pass);
/* TODO: OPTI: Filter all cascade in one/two draw call */
for (linfo->current_shadow_cascade = 0;
@@ -1114,11 +1171,10 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
/* Copy using a small 3x3 box filter */
linfo->filter_size = linfo->shadow_render_data.stored_texel_size * ((filter_pixel_size > 1.0f) ? 1.0f : 0.0f);
- DRW_framebuffer_texture_layer_attach(
+ GPU_framebuffer_texture_layer_attach(
sldata->shadow_store_fb, sldata->shadow_cascade_blur, 0, linfo->current_shadow_cascade, 0);
- DRW_framebuffer_bind(sldata->shadow_store_fb);
+ GPU_framebuffer_bind(sldata->shadow_store_fb);
DRW_draw_pass(psl->shadow_cascade_copy_pass);
- DRW_framebuffer_texture_detach(sldata->shadow_cascade_blur);
/* Push it to shadowmap array and blur more */
@@ -1142,15 +1198,16 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data);
int layer = evscd->layer_id + linfo->current_shadow_cascade;
- DRW_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, layer, 0);
- DRW_framebuffer_bind(sldata->shadow_store_fb);
+ GPU_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, layer, 0);
+ GPU_framebuffer_bind(sldata->shadow_store_fb);
DRW_draw_pass(psl->shadow_cascade_store_pass);
}
}
- DRW_framebuffer_texture_detach(sldata->shadow_cascade_target);
DRW_stats_group_end();
+ DRW_viewport_matrix_override_set_all(&saved_mats);
+
DRW_uniformbuffer_update(sldata->light_ubo, &linfo->light_data);
DRW_uniformbuffer_update(sldata->shadow_ubo, &linfo->shadow_data); /* Update all data at once */
}
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index cde14f0efc3..d146fda5373 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -52,6 +52,7 @@
/* *********** STATIC *********** */
static struct {
+ char *shadow_shader_lib;
char *frag_shader_lib;
char *volume_shader_lib;
@@ -70,7 +71,6 @@ static struct {
unsigned int sss_count;
- float view_vecs[2][4];
float alpha_hash_offset;
float noise_offsets[3];
} e_data = {NULL}; /* Engine data */
@@ -89,6 +89,7 @@ extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_direct_lib_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
extern char datatoc_irradiance_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
extern char datatoc_lit_surface_frag_glsl[];
@@ -145,9 +146,9 @@ static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
tex = DRW_texture_create_2D(w, h, DRW_TEX_RG_16, DRW_TEX_FILTER, (float *)texels);
DRWFboTexture tex_filter = {&tex, DRW_TEX_RG_16, DRW_TEX_FILTER};
- DRW_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
+ GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
- DRW_framebuffer_bind(fb);
+ GPU_framebuffer_bind(fb);
DRW_draw_pass(pass);
float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
@@ -207,9 +208,9 @@ static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
tex = DRW_texture_create_2D(w, h, DRW_TEX_R_16, DRW_TEX_FILTER, (float *)texels);
DRWFboTexture tex_filter = {&tex, DRW_TEX_R_16, DRW_TEX_FILTER};
- DRW_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
+ GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
- DRW_framebuffer_bind(fb);
+ GPU_framebuffer_bind(fb);
float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
@@ -223,7 +224,7 @@ static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
a2 = powf(roughness, 4.0f);
DRW_draw_pass(pass);
- DRW_framebuffer_read_data(0, 0, w, h, 3, 0, data);
+ GPU_framebuffer_read_data(0, 0, w, h, 3, 0, data);
#if 1
fprintf(f, "\t{\n\t\t");
@@ -375,46 +376,47 @@ static void add_standard_uniforms(
DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(shgrp, "clip_block", sldata->clip_ubo);
/* TODO if glossy or diffuse bsdf */
if (true) {
DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
- DRW_shgroup_uniform_buffer(shgrp, "shadowTexture", &sldata->shadow_pool);
- DRW_shgroup_uniform_buffer(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
+ DRW_shgroup_uniform_texture_ref(shgrp, "shadowTexture", &sldata->shadow_pool);
+ DRW_shgroup_uniform_texture_ref(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
if ((vedata->stl->effects->enabled_effects & EFFECT_GTAO) != 0) {
- DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &vedata->txl->gtao_horizons);
+ DRW_shgroup_uniform_texture_ref(shgrp, "horizonBuffer", &vedata->stl->effects->gtao_horizons);
}
else {
/* Use maxzbuffer as fallback to avoid sampling problem on certain platform, see: T52593 */
- DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &vedata->txl->maxzbuffer);
+ DRW_shgroup_uniform_texture_ref(shgrp, "horizonBuffer", &vedata->txl->maxzbuffer);
}
}
/* TODO if diffuse bsdf */
if (true) {
- DRW_shgroup_uniform_buffer(shgrp, "irradianceGrid", &sldata->irradiance_pool);
+ DRW_shgroup_uniform_texture_ref(shgrp, "irradianceGrid", &sldata->irradiance_pool);
}
/* TODO if glossy bsdf */
if (true) {
- DRW_shgroup_uniform_buffer(shgrp, "probeCubes", &sldata->probe_pool);
- DRW_shgroup_uniform_buffer(shgrp, "probePlanars", &vedata->txl->planar_pool);
+ DRW_shgroup_uniform_texture_ref(shgrp, "probeCubes", &sldata->probe_pool);
+ DRW_shgroup_uniform_texture_ref(shgrp, "probePlanars", &vedata->txl->planar_pool);
DRW_shgroup_uniform_int(shgrp, "outputSsrId", ssr_id, 1);
}
if (use_ssrefraction) {
BLI_assert(refract_depth != NULL);
DRW_shgroup_uniform_float(shgrp, "refractionDepth", refract_depth, 1);
- DRW_shgroup_uniform_buffer(shgrp, "colorBuffer", &vedata->txl->refract_color);
+ DRW_shgroup_uniform_texture_ref(shgrp, "colorBuffer", &vedata->txl->refract_color);
}
if ((vedata->stl->effects->enabled_effects & EFFECT_VOLUMETRIC) != 0 &&
use_alpha_blend)
{
/* Do not use history buffers as they already have been swapped */
- DRW_shgroup_uniform_buffer(shgrp, "inScattering", &vedata->txl->volume_scatter);
- DRW_shgroup_uniform_buffer(shgrp, "inTransmittance", &vedata->txl->volume_transmittance);
+ DRW_shgroup_uniform_texture_ref(shgrp, "inScattering", &vedata->txl->volume_scatter);
+ DRW_shgroup_uniform_texture_ref(shgrp, "inTransmittance", &vedata->txl->volume_transmittance);
}
}
@@ -488,7 +490,7 @@ static void eevee_init_util_texture(void)
MEM_freeN(texels);
}
-void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, double offsets[3])
+void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const double offsets[3])
{
e_data.noise_offsets[0] = offsets[0];
e_data.noise_offsets[1] = offsets[1];
@@ -496,17 +498,55 @@ void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, double
/* Attach & detach because we don't currently support multiple FB per texture,
* and this would be the case for multiple viewport. */
- DRW_framebuffer_texture_layer_attach(fbl->update_noise_fb, e_data.util_tex, 0, 2, 0);
- DRW_framebuffer_bind(fbl->update_noise_fb);
+ GPU_framebuffer_bind(fbl->update_noise_fb);
DRW_draw_pass(psl->update_noise_pass);
- DRW_framebuffer_texture_detach(e_data.util_tex);
+}
+
+static void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_viewvecs)[4])
+{
+ /* view vectors for the corners of the view frustum.
+ * Can be used to recreate the world space position easily */
+ float view_vecs[4][4] = {
+ {-1.0f, -1.0f, -1.0f, 1.0f},
+ { 1.0f, -1.0f, -1.0f, 1.0f},
+ {-1.0f, 1.0f, -1.0f, 1.0f},
+ {-1.0f, -1.0f, 1.0f, 1.0f}
+ };
+
+ /* convert the view vectors to view space */
+ const bool is_persp = (winmat[3][3] == 0.0f);
+ for (int i = 0; i < 4; i++) {
+ mul_project_m4_v3(invproj, view_vecs[i]);
+ /* normalized trick see:
+ * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
+ if (is_persp) {
+ /* Divide XY by Z. */
+ mul_v2_fl(view_vecs[i], 1.0f / view_vecs[i][2]);
+ }
+ }
+
+ /**
+ * If ortho : view_vecs[0] is the near-bottom-left corner of the frustum and
+ * view_vecs[1] is the vector going from the near-bottom-left corner to
+ * the far-top-right corner.
+ * If Persp : view_vecs[0].xy and view_vecs[1].xy are respectively the bottom-left corner
+ * when Z = 1, and top-left corner if Z = 1.
+ * view_vecs[0].z the near clip distance and view_vecs[1].z is the (signed)
+ * distance from the near plane to the far clip plane.
+ **/
+ copy_v4_v4(r_viewvecs[0], view_vecs[0]);
+
+ /* we need to store the differences */
+ r_viewvecs[1][0] = view_vecs[1][0] - view_vecs[0][0];
+ r_viewvecs[1][1] = view_vecs[2][1] - view_vecs[0][1];
+ r_viewvecs[1][2] = view_vecs[3][2] - view_vecs[0][2];
}
void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl)
{
if (!e_data.frag_shader_lib) {
/* Shaders */
- e_data.frag_shader_lib = BLI_string_joinN(
+ e_data.shadow_shader_lib = BLI_string_joinN(
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
@@ -530,7 +570,12 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, E
datatoc_lit_surface_frag_glsl,
datatoc_volumetric_lib_glsl);
+ e_data.frag_shader_lib = BLI_string_joinN(
+ datatoc_common_view_lib_glsl,
+ e_data.shadow_shader_lib);
+
e_data.volume_shader_lib = BLI_string_joinN(
+ datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_ambient_occlusion_lib_glsl,
@@ -584,67 +629,32 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, E
eevee_init_noise_texture();
}
- /* Alpha hash scale: Non-flickering size if we are not refining the render. */
if (!DRW_state_is_image_render() &&
- (((stl->effects->enabled_effects & EFFECT_TAA) == 0) ||
- (stl->effects->taa_current_sample == 1)))
+ ((stl->effects->enabled_effects & EFFECT_TAA) == 0))
{
e_data.alpha_hash_offset = 0.0f;
}
else {
double r;
- BLI_halton_1D(5, 0.0, stl->effects->taa_current_sample, &r);
+ BLI_halton_1D(5, 0.0, stl->effects->taa_current_sample - 1, &r);
e_data.alpha_hash_offset = (float)r;
}
{
/* Update view_vecs */
- const bool is_persp = DRW_viewport_is_persp_get();
float invproj[4][4], winmat[4][4];
- /* view vectors for the corners of the view frustum.
- * Can be used to recreate the world space position easily */
- float view_vecs[3][4] = {
- {-1.0f, -1.0f, -1.0f, 1.0f},
- {1.0f, -1.0f, -1.0f, 1.0f},
- {-1.0f, 1.0f, -1.0f, 1.0f}
- };
-
- /* invert the view matrix */
DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
- invert_m4_m4(invproj, winmat);
-
- /* convert the view vectors to view space */
- for (int i = 0; i < 3; i++) {
- mul_m4_v4(invproj, view_vecs[i]);
- /* normalized trick see:
- * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
- mul_v3_fl(view_vecs[i], 1.0f / view_vecs[i][3]);
- if (is_persp)
- mul_v3_fl(view_vecs[i], 1.0f / view_vecs[i][2]);
- view_vecs[i][3] = 1.0;
- }
-
- copy_v4_v4(sldata->common_data.view_vecs[0], view_vecs[0]);
- copy_v4_v4(sldata->common_data.view_vecs[1], view_vecs[1]);
+ DRW_viewport_matrix_get(invproj, DRW_MAT_WININV);
- /* we need to store the differences */
- sldata->common_data.view_vecs[1][0] -= view_vecs[0][0];
- sldata->common_data.view_vecs[1][1] = view_vecs[2][1] - view_vecs[0][1];
-
- /* calculate a depth offset as well */
- if (!is_persp) {
- float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
- mul_m4_v4(invproj, vec_far);
- mul_v3_fl(vec_far, 1.0f / vec_far[3]);
- sldata->common_data.view_vecs[1][2] = vec_far[2] - view_vecs[0][2];
- }
+ EEVEE_update_viewvecs(invproj, winmat, sldata->common_data.view_vecs);
}
{
/* Update noise Framebuffer. */
- if (fbl->update_noise_fb == NULL) {
- fbl->update_noise_fb = DRW_framebuffer_create();
- }
+ GPU_framebuffer_ensure_config(&fbl->update_noise_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE_LAYER(e_data.util_tex, 2)
+ });
}
}
@@ -653,12 +663,12 @@ struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, Wor
const void *engine = &DRW_engine_viewport_eevee_type;
const int options = VAR_WORLD_PROBE;
- GPUMaterial *mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine, options);
+ GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options);
if (mat != NULL) {
return mat;
}
- return GPU_material_from_nodetree(
- scene, wo->nodetree, &wo->gpumaterial, engine, options,
+ return DRW_shader_create_from_world(
+ scene, wo, engine, options,
datatoc_background_vert_glsl, NULL, e_data.frag_shader_lib,
SHADER_DEFINES "#define PROBE_CAPTURE\n");
}
@@ -668,12 +678,12 @@ struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, Wor
const void *engine = &DRW_engine_viewport_eevee_type;
int options = VAR_WORLD_BACKGROUND;
- GPUMaterial *mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine, options);
+ GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options);
if (mat != NULL) {
return mat;
}
- return GPU_material_from_nodetree(
- scene, wo->nodetree, &wo->gpumaterial, engine, options,
+ return DRW_shader_create_from_world(
+ scene, wo, engine, options,
datatoc_background_vert_glsl, NULL, e_data.frag_shader_lib,
SHADER_DEFINES "#define WORLD_BACKGROUND\n");
}
@@ -683,15 +693,15 @@ struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *
const void *engine = &DRW_engine_viewport_eevee_type;
int options = VAR_WORLD_VOLUME;
- GPUMaterial *mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine, options);
+ GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options);
if (mat != NULL) {
return mat;
}
char *defines = eevee_get_volume_defines(options);
- mat = GPU_material_from_nodetree(
- scene, wo->nodetree, &wo->gpumaterial, engine, options,
+ mat = DRW_shader_create_from_world(
+ scene, wo, engine, options,
datatoc_volumetric_vert_glsl, datatoc_volumetric_geom_glsl, e_data.volume_shader_lib,
defines);
@@ -718,15 +728,15 @@ struct GPUMaterial *EEVEE_material_mesh_get(
options |= eevee_material_shadow_option(shadow_method);
- GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine, options);
+ GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options);
if (mat) {
return mat;
}
char *defines = eevee_get_defines(options);
- mat = GPU_material_from_nodetree(
- scene, ma->nodetree, &ma->gpumaterial, engine, options,
+ mat = DRW_shader_create_from_material(
+ scene, ma, engine, options,
datatoc_lit_surface_vert_glsl, NULL, e_data.frag_shader_lib,
defines);
@@ -740,15 +750,15 @@ struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material
const void *engine = &DRW_engine_viewport_eevee_type;
int options = VAR_MAT_VOLUME;
- GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine, options);
+ GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options);
if (mat != NULL) {
return mat;
}
char *defines = eevee_get_volume_defines(options);
- mat = GPU_material_from_nodetree(
- scene, ma->nodetree, &ma->gpumaterial, engine, options,
+ mat = DRW_shader_create_from_material(
+ scene, ma, engine, options,
datatoc_volumetric_vert_glsl, datatoc_volumetric_geom_glsl, e_data.volume_shader_lib,
defines);
@@ -774,7 +784,7 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(
if (is_shadow)
options |= VAR_MAT_SHADOW;
- GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine, options);
+ GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options);
if (mat) {
return mat;
}
@@ -782,11 +792,11 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(
char *defines = eevee_get_defines(options);
char *frag_str = BLI_string_joinN(
- e_data.frag_shader_lib,
+ (is_shadow) ? e_data.shadow_shader_lib : e_data.frag_shader_lib,
datatoc_prepass_frag_glsl);
- mat = GPU_material_from_nodetree(
- scene, ma->nodetree, &ma->gpumaterial, engine, options,
+ mat = DRW_shader_create_from_material(
+ scene, ma, engine, options,
(is_shadow) ? datatoc_shadow_vert_glsl : datatoc_lit_surface_vert_glsl,
(is_shadow) ? datatoc_shadow_geom_glsl : NULL,
frag_str,
@@ -807,7 +817,7 @@ struct GPUMaterial *EEVEE_material_hair_get(
if (use_fibers) {
options |= VAR_MAT_HAIR_FIBERS;
}
- GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine, options);
+ GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options);
if (mat) {
return mat;
}
@@ -823,8 +833,8 @@ struct GPUMaterial *EEVEE_material_hair_get(
char *defines = eevee_get_defines(options);
- mat = GPU_material_from_nodetree(
- scene, ma->nodetree, &ma->gpumaterial, engine, options,
+ mat = DRW_shader_create_from_material(
+ scene, ma, engine, options,
vert_str, NULL, e_data.frag_shader_lib,
defines);
@@ -891,13 +901,15 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(
vedata->psl->default_pass[options] = DRW_pass_create("Default Lit Pass", state);
DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]);
+ /* XXX / WATCH: This creates non persistent binds for the ubos and textures.
+ * But it's currently OK because the following shgroups does not add any bind. */
add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false);
}
return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]);
}
-void EEVEE_materials_cache_init(EEVEE_Data *vedata)
+void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
@@ -924,17 +936,25 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata)
col = &wo->horr;
if (wo->use_nodes && wo->nodetree) {
+ static float error_col[3] = {1.0f, 0.0f, 1.0f};
+ static float compile_col[3] = {0.5f, 0.5f, 0.5f};
struct GPUMaterial *gpumat = EEVEE_material_world_background_get(scene, wo);
- grp = DRW_shgroup_material_create(gpumat, psl->background_pass);
- if (grp) {
- DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
- DRW_shgroup_call_add(grp, geom, NULL);
- }
- else {
- /* Shader failed : pink background */
- static float pink[3] = {1.0f, 0.0f, 1.0f};
- col = pink;
+ switch (GPU_material_status(gpumat)) {
+ case GPU_MAT_SUCCESS:
+ grp = DRW_shgroup_material_create(gpumat, psl->background_pass);
+ DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
+ DRW_shgroup_call_add(grp, geom, NULL);
+ break;
+ case GPU_MAT_QUEUED:
+ sldata->probes->all_materials_updated = false;
+ /* TODO Bypass probe compilation. */
+ col = compile_col;
+ break;
+ case GPU_MAT_FAILED:
+ default:
+ col = error_col;
+ break;
}
}
}
@@ -963,11 +983,15 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata)
psl->depth_pass_clip = DRW_pass_create("Depth Pass Clip", state);
stl->g_data->depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->depth_pass_clip);
stl->g_data->hair_fibers_depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_hair_fiber_clip_sh, psl->depth_pass_clip);
+ DRW_shgroup_uniform_block(stl->g_data->depth_shgrp_clip, "clip_block", sldata->clip_ubo);
+ DRW_shgroup_uniform_block(stl->g_data->hair_fibers_depth_shgrp_clip, "clip_block", sldata->clip_ubo);
state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CLIP_PLANES | DRW_STATE_CULL_BACK;
psl->depth_pass_clip_cull = DRW_pass_create("Depth Pass Cull Clip", state);
stl->g_data->depth_shgrp_clip_cull = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->depth_pass_clip_cull);
stl->g_data->hair_fibers_depth_shgrp_clip_cull = DRW_shgroup_create(e_data.default_prepass_hair_fiber_clip_sh, psl->depth_pass_clip_cull);
+ DRW_shgroup_uniform_block(stl->g_data->depth_shgrp_clip_cull, "clip_block", sldata->clip_ubo);
+ DRW_shgroup_uniform_block(stl->g_data->hair_fibers_depth_shgrp_clip_cull, "clip_block", sldata->clip_ubo);
}
{
@@ -987,10 +1011,12 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata)
state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE;
psl->refract_depth_pass_clip = DRW_pass_create("Refract Depth Pass Clip", state);
stl->g_data->refract_depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip);
+ DRW_shgroup_uniform_block(stl->g_data->refract_depth_shgrp_clip, "clip_block", sldata->clip_ubo);
state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CLIP_PLANES | DRW_STATE_CULL_BACK;
psl->refract_depth_pass_clip_cull = DRW_pass_create("Refract Depth Pass Cull Clip", state);
stl->g_data->refract_depth_shgrp_clip_cull = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip_cull);
+ DRW_shgroup_uniform_block(stl->g_data->refract_depth_shgrp_clip_cull, "clip_block", sldata->clip_ubo);
}
{
@@ -1080,53 +1106,29 @@ static void material_opaque(
}
if (use_gpumat) {
+ static float error_col[3] = {1.0f, 0.0f, 1.0f};
+ static float compile_col[3] = {0.5f, 0.5f, 0.5f};
+ static float half = 0.5f;
+
/* Shading */
*gpumat = EEVEE_material_mesh_get(scene, ma, vedata, false, false, use_refract,
use_sss, use_translucency, linfo->shadow_method);
- *shgrp = DRW_shgroup_material_create(*gpumat,
- (use_refract) ? psl->refract_pass :
- (use_sss) ? psl->sss_pass : psl->material_pass);
- if (*shgrp) {
- static int no_ssr = -1;
- static int first_ssr = 1;
- int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_refract) ? &first_ssr : &no_ssr;
- add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false);
-
- if (use_sss) {
- struct GPUTexture *sss_tex_profile = NULL;
- struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(*gpumat,
- stl->effects->sss_sample_count,
- &sss_tex_profile);
-
- if (sss_profile) {
- if (use_translucency) {
- DRW_shgroup_uniform_block(*shgrp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_texture(*shgrp, "sssTexProfile", sss_tex_profile);
- }
-
- DRW_shgroup_stencil_mask(*shgrp, e_data.sss_count + 1);
- EEVEE_subsurface_add_pass(sldata, vedata, e_data.sss_count + 1, sss_profile);
- e_data.sss_count++;
- }
- }
- }
- else {
- /* Shader failed : pink color */
- static float col[3] = {1.0f, 0.0f, 1.0f};
- static float half = 0.5f;
-
- color_p = col;
- metal_p = spec_p = rough_p = &half;
- }
+ GPUMaterialStatus status_mat_surface = GPU_material_status(*gpumat);
/* Alpha CLipped : Discard pixel from depth pass, then
* fail the depth test for shading. */
if (ELEM(ma->blend_method, MA_BM_CLIP, MA_BM_HASHED)) {
*gpumat_depth = EEVEE_material_mesh_depth_get(scene, ma,
- (ma->blend_method == MA_BM_HASHED), false);
+ (ma->blend_method == MA_BM_HASHED), false);
- if (use_refract) {
+ GPUMaterialStatus status_mat_depth = GPU_material_status(*gpumat_depth);
+ if (status_mat_depth != GPU_MAT_SUCCESS) {
+ /* Mixing both flags. If depth shader fails, show it to the user by not using
+ * the surface shader. */
+ status_mat_surface = status_mat_depth;
+ }
+ else if (use_refract) {
*shgrp_depth = DRW_shgroup_material_create(*gpumat_depth, (do_cull) ? psl->refract_depth_pass_cull : psl->refract_depth_pass);
*shgrp_depth_clip = DRW_shgroup_material_create(*gpumat_depth, (do_cull) ? psl->refract_depth_pass_clip_cull : psl->refract_depth_pass_clip);
}
@@ -1137,6 +1139,7 @@ static void material_opaque(
if (*shgrp_depth != NULL) {
add_standard_uniforms(*shgrp_depth, sldata, vedata, NULL, NULL, false, false);
+ add_standard_uniforms(*shgrp_depth_clip, sldata, vedata, NULL, NULL, false, false);
if (ma->blend_method == MA_BM_CLIP) {
DRW_shgroup_uniform_float(*shgrp_depth, "alphaThreshold", &ma->alpha_threshold, 1);
@@ -1148,6 +1151,59 @@ static void material_opaque(
}
}
}
+
+ switch (status_mat_surface) {
+ case GPU_MAT_SUCCESS:
+ {
+ static int no_ssr = -1;
+ static int first_ssr = 1;
+ int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_refract) ? &first_ssr : &no_ssr;
+
+ *shgrp = DRW_shgroup_material_create(*gpumat,
+ (use_refract) ? psl->refract_pass :
+ (use_sss) ? psl->sss_pass : psl->material_pass);
+ add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false);
+
+ if (use_sss) {
+ struct GPUTexture *sss_tex_profile = NULL;
+ struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(*gpumat,
+ stl->effects->sss_sample_count,
+ &sss_tex_profile);
+
+ if (sss_profile) {
+ if (use_translucency) {
+ DRW_shgroup_uniform_block(*shgrp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_texture(*shgrp, "sssTexProfile", sss_tex_profile);
+ }
+
+ /* Limit of 8 bit stencil buffer. ID 255 is refraction. */
+ if (e_data.sss_count < 254) {
+ DRW_shgroup_stencil_mask(*shgrp, e_data.sss_count + 1);
+ EEVEE_subsurface_add_pass(sldata, vedata, e_data.sss_count + 1, sss_profile);
+ e_data.sss_count++;
+ }
+ else {
+ /* TODO : display message. */
+ printf("Error: Too many different Subsurface shader in the scene.\n");
+ }
+ }
+ }
+ break;
+ }
+ case GPU_MAT_QUEUED:
+ {
+ sldata->probes->all_materials_updated = false;
+ /* TODO Bypass probe compilation. */
+ color_p = compile_col;
+ metal_p = spec_p = rough_p = &half;
+ break;
+ }
+ case GPU_MAT_FAILED:
+ default:
+ color_p = error_col;
+ metal_p = spec_p = rough_p = &half;
+ break;
+ }
}
/* Fallback to default shader */
@@ -1172,7 +1228,7 @@ static void material_opaque(
}
}
- emsg = MEM_mallocN(sizeof("EeveeMaterialShadingGroups"), "EeveeMaterialShadingGroups");
+ emsg = MEM_mallocN(sizeof(EeveeMaterialShadingGroups), "EeveeMaterialShadingGroups");
emsg->shading_grp = *shgrp;
emsg->depth_grp = *shgrp_depth;
emsg->depth_clip_grp = *shgrp_depth_clip;
@@ -1197,23 +1253,37 @@ static void material_transparent(
float *rough_p = &ma->gloss_mir;
if (ma->use_nodes && ma->nodetree) {
+ static float error_col[3] = {1.0f, 0.0f, 1.0f};
+ static float compile_col[3] = {0.5f, 0.5f, 0.5f};
+ static float half = 0.5f;
+
/* Shading */
*gpumat = EEVEE_material_mesh_get(scene, ma, vedata, true, (ma->blend_method == MA_BM_MULTIPLY), use_refract,
false, false, linfo->shadow_method);
- *shgrp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass);
- if (*shgrp) {
- static int ssr_id = -1; /* TODO transparent SSR */
- bool use_blend = (ma->blend_method & MA_BM_BLEND) != 0;
- add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id, &ma->refract_depth, use_refract, use_blend);
- }
- else {
- /* Shader failed : pink color */
- static float col[3] = {1.0f, 0.0f, 1.0f};
- static float half = 0.5f;
+ switch (GPU_material_status(*gpumat)) {
+ case GPU_MAT_SUCCESS:
+ {
+ static int ssr_id = -1; /* TODO transparent SSR */
+ bool use_blend = (ma->blend_method & MA_BM_BLEND) != 0;
- color_p = col;
- metal_p = spec_p = rough_p = &half;
+ *shgrp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass);
+ add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id, &ma->refract_depth, use_refract, use_blend);
+ break;
+ }
+ case GPU_MAT_QUEUED:
+ {
+ sldata->probes->all_materials_updated = false;
+ /* TODO Bypass probe compilation. */
+ color_p = compile_col;
+ metal_p = spec_p = rough_p = &half;
+ break;
+ }
+ case GPU_MAT_FAILED:
+ default:
+ color_p = error_col;
+ metal_p = spec_p = rough_p = &half;
+ break;
}
}
@@ -1259,6 +1329,7 @@ static void material_transparent(
/* Depth prepass */
if (use_prepass) {
*shgrp_depth = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass);
+ DRW_shgroup_uniform_block(*shgrp_depth, "clip_block", sldata->clip_ubo);
cur_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
@@ -1442,8 +1513,8 @@ static void material_hair(
void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob)
{
- EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
GHash *material_hash = stl->g_data->material_hash;
@@ -1451,7 +1522,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld
IDProperty *ces_mode_ob = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_OBJECT, "");
const bool do_cull = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_backface_culling");
const bool is_active = (ob == draw_ctx->obact);
- const bool is_sculpt_mode = is_active && (ob->mode & OB_MODE_SCULPT) != 0;
+ const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0;
#if 0
const bool is_sculpt_mode_draw = is_sculpt_mode && (draw_ctx->v3d->flag2 & V3D_SHOW_MODE_SHADE_OVERRIDE) == 0;
#else
@@ -1559,7 +1630,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld
struct GPUMaterial *gpumat;
switch (ma->blend_shadow) {
case MA_BS_SOLID:
- EEVEE_lights_cache_shcaster_add(sldata, psl, mat_geom[i], ob->obmat);
+ EEVEE_lights_cache_shcaster_add(sldata, stl, mat_geom[i], ob);
break;
case MA_BS_CLIP:
gpumat = EEVEE_material_mesh_depth_get(scene, ma, false, true);
@@ -1575,7 +1646,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld
}
}
else {
- EEVEE_lights_cache_shcaster_add(sldata, psl, mat_geom[i], ob->obmat);
+ EEVEE_lights_cache_shcaster_add(sldata, stl, mat_geom[i], ob);
}
}
}
@@ -1587,7 +1658,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld
}
if (ob->type == OB_MESH) {
- if (ob != draw_ctx->scene->obedit) {
+ if (ob != draw_ctx->object_edit) {
for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_ParticleSystem) {
ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys;
@@ -1619,6 +1690,7 @@ void EEVEE_materials_free(void)
for (int i = 0; i < VAR_MAT_MAX; ++i) {
DRW_SHADER_FREE_SAFE(e_data.default_lit[i]);
}
+ MEM_SAFE_FREE(e_data.shadow_shader_lib);
MEM_SAFE_FREE(e_data.frag_shader_lib);
MEM_SAFE_FREE(e_data.volume_shader_lib);
DRW_SHADER_FREE_SAFE(e_data.default_prepass_sh);
diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c
new file mode 100644
index 00000000000..1675142613d
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_mist.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file eevee_mist.c
+ * \ingroup draw_engine
+ *
+ * Implementation of Blender Mist pass.
+ * IMPORTANT: This is a "post process" of the Z depth so it will lack any transparent objects.
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "DNA_world_types.h"
+
+#include "BLI_string_utils.h"
+
+#include "eevee_private.h"
+
+extern char datatoc_common_view_lib_glsl[];
+extern char datatoc_common_uniforms_lib_glsl[];
+extern char datatoc_bsdf_common_lib_glsl[];
+extern char datatoc_effect_mist_frag_glsl[];
+
+static struct {
+ struct GPUShader *mist_sh;
+} e_data = {NULL}; /* Engine data */
+
+void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_PrivateData *g_data = stl->g_data;
+ Scene *scene = draw_ctx->scene;
+
+ float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ if (e_data.mist_sh == NULL) {
+ char *frag_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl,
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_effect_mist_frag_glsl);
+
+ e_data.mist_sh = DRW_shader_create_fullscreen(frag_str, "#define FIRST_PASS\n");
+
+ MEM_freeN(frag_str);
+ }
+
+ /* Create FrameBuffer. */
+ DRW_texture_ensure_fullscreen_2D(&txl->mist_accum, DRW_TEX_R_32, 0); /* Should be enough precision for many samples. */
+
+ GPU_framebuffer_ensure_config(&fbl->mist_accum_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->mist_accum)
+ });
+
+ /* Clear texture. */
+ GPU_framebuffer_bind(fbl->mist_accum_fb);
+ GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear);
+
+ /* Mist settings. */
+ if (scene && scene->world) {
+ g_data->mist_start = scene->world->miststa;
+ g_data->mist_inv_dist = (scene->world->mistdist > 0.0f) ? 1.0f / scene->world->mistdist : 0.0f;
+
+ switch (scene->world->mistype) {
+ case WO_MIST_QUADRATIC:
+ g_data->mist_falloff = 2.0f;
+ break;
+ case WO_MIST_LINEAR:
+ g_data->mist_falloff = 1.0f;
+ break;
+ case WO_MIST_INVERSE_QUADRATIC:
+ g_data->mist_falloff = 0.5f;
+ break;
+ }
+ }
+ else {
+ float near = -sldata->common_data.view_vecs[0][2];
+ float range = sldata->common_data.view_vecs[1][2];
+ /* Fallback */
+ g_data->mist_start = near;
+ g_data->mist_inv_dist = 1.0f / fabsf(range);
+ g_data->mist_falloff = 1.0f;
+ }
+
+ /* XXX ??!! WHY? If not it does not match cycles. */
+ g_data->mist_falloff *= 0.5f;
+
+ /* Create Pass and shgroup. */
+ psl->mist_accum_ps = DRW_pass_create("Mist Accum", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.mist_sh, psl->mist_accum_ps);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_vec3(grp, "mistSettings", &g_data->mist_start, 1);
+ DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+}
+
+void EEVEE_mist_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_PassList *psl = vedata->psl;
+
+ if (fbl->mist_accum_fb != NULL) {
+ GPU_framebuffer_bind(fbl->mist_accum_fb);
+ DRW_draw_pass(psl->mist_accum_ps);
+
+ /* Restore */
+ GPU_framebuffer_bind(fbl->main_fb);
+ }
+}
+
+void EEVEE_mist_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.mist_sh);
+}
diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c
index b05fbf8c7fb..9b19163c8d7 100644
--- a/source/blender/draw/engines/eevee/eevee_motion_blur.c
+++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c
@@ -59,7 +59,6 @@ static void eevee_motion_blur_camera_get_matrix_at_time(
float time,
float r_mat[4][4])
{
- EvaluationContext eval_ctx;
float obmat[4][4];
/* HACK */
@@ -68,18 +67,9 @@ static void eevee_motion_blur_camera_get_matrix_at_time(
memcpy(&camdata_cpy, camera->data, sizeof(camdata_cpy));
cam_cpy.data = &camdata_cpy;
- /* NOTE: Mode corresponds to old usage of eval_ctx from viewport (which was
- * actually coming from bmain). It was always DAG_EVAL_VIEWPORT. For F12
- * render this should be DAG_EVAL_RENDER, but the whole hack is to be
- * reconsidered first anyway.
- */
const DRWContextState *draw_ctx = DRW_context_state_get();
- DEG_evaluation_context_init_from_scene(
- &eval_ctx,
- scene,
- draw_ctx->view_layer,
- draw_ctx->engine_type,
- DAG_EVAL_VIEWPORT);
+ /* We will be modifying time, so we create copy of eval_ctx. */
+ EvaluationContext eval_ctx = draw_ctx->eval_ctx;
eval_ctx.ctime = time;
/* Past matrix */
@@ -93,27 +83,15 @@ static void eevee_motion_blur_camera_get_matrix_at_time(
CameraParams params;
BKE_camera_params_init(&params);
- /* copy of BKE_camera_params_from_view3d */
- {
- params.lens = v3d->lens;
- params.clipsta = v3d->near;
- params.clipend = v3d->far;
-
- /* camera view */
+ if (v3d != NULL) {
+ BKE_camera_params_from_view3d(&params, draw_ctx->depsgraph, v3d, rv3d);
+ BKE_camera_params_compute_viewplane(&params, ar->winx, ar->winy, 1.0f, 1.0f);
+ }
+ else {
BKE_camera_params_from_object(&params, &cam_cpy);
-
- params.zoom = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
-
- params.offsetx = 2.0f * rv3d->camdx * params.zoom;
- params.offsety = 2.0f * rv3d->camdy * params.zoom;
-
- params.shiftx *= params.zoom;
- params.shifty *= params.zoom;
-
- params.zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB / params.zoom;
+ BKE_camera_params_compute_viewplane(&params, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp);
}
- BKE_camera_params_compute_viewplane(&params, ar->winx, ar->winy, 1.0f, 1.0f);
BKE_camera_params_compute_matrix(&params);
/* FIXME Should be done per view (MULTIVIEW) */
@@ -127,7 +105,7 @@ static void eevee_create_shader_motion_blur(void)
e_data.motion_blur_sh = DRW_shader_create_fullscreen(datatoc_effect_motion_blur_frag_glsl, NULL);
}
-int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, Object *camera)
{
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
@@ -144,11 +122,11 @@ int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda
if (BKE_collection_engine_property_value_get_bool(props, "motion_blur_enable")) {
/* Update Motion Blur Matrices */
- if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ if (camera) {
float persmat[4][4];
float ctime = BKE_scene_frame_get(scene);
float delta = BKE_collection_engine_property_value_get_float(props, "motion_blur_shutter");
- Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera);
+ Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, camera);
/* Current matrix */
eevee_motion_blur_camera_get_matrix_at_time(scene,
@@ -212,8 +190,8 @@ void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
DRW_shgroup_uniform_int(grp, "samples", &effects->motion_blur_samples, 1);
DRW_shgroup_uniform_mat4(grp, "currInvViewProjMatrix", (float *)effects->current_ndc_to_world);
DRW_shgroup_uniform_mat4(grp, "pastViewProjMatrix", (float *)effects->past_world_to_ndc);
- DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->source_buffer);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_call_add(grp, quad, NULL);
}
}
@@ -228,7 +206,7 @@ void EEVEE_motion_blur_draw(EEVEE_Data *vedata)
/* Motion Blur */
if ((effects->enabled_effects & EFFECT_MOTION_BLUR) != 0) {
- DRW_framebuffer_bind(effects->target_buffer);
+ GPU_framebuffer_bind(effects->target_buffer);
DRW_draw_pass(psl->motion_blur);
SWAP_BUFFERS();
}
diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c
index 9da438e825f..9fd7f6d4126 100644
--- a/source/blender/draw/engines/eevee/eevee_occlusion.c
+++ b/source/blender/draw/engines/eevee/eevee_occlusion.c
@@ -44,6 +44,7 @@ static struct {
} e_data = {NULL}; /* Engine data */
extern char datatoc_ambient_occlusion_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_effect_gtao_frag_glsl[];
@@ -51,6 +52,7 @@ extern char datatoc_effect_gtao_frag_glsl[];
static void eevee_create_shader_occlusion(void)
{
char *frag_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_ambient_occlusion_lib_glsl,
@@ -66,9 +68,9 @@ static void eevee_create_shader_occlusion(void)
int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
- EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
- EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
@@ -78,6 +80,7 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
if (BKE_collection_engine_property_value_get_bool(props, "gtao_enable")) {
const float *viewport_size = DRW_viewport_size_get();
+ const int fs_size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
/* Shaders */
if (!e_data.gtao_sh) {
@@ -98,31 +101,82 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
common_data->ao_bounce_fac = (float)BKE_collection_engine_property_value_get_bool(props, "gtao_bounce");
- DRWFboTexture tex = {&txl->gtao_horizons, DRW_TEX_RGBA_8, 0};
-
- DRW_framebuffer_init(&fbl->gtao_fb, &draw_engine_eevee_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex, 1);
+ effects->gtao_horizons = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], DRW_TEX_RGBA_8,
+ &draw_engine_eevee_type);
+ GPU_framebuffer_ensure_config(&fbl->gtao_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->gtao_horizons)
+ });
if (G.debug_value == 6) {
- DRWFboTexture tex_debug = {&stl->g_data->gtao_horizons_debug, DRW_TEX_RGBA_8, DRW_TEX_TEMP};
-
- DRW_framebuffer_init(&fbl->gtao_debug_fb, &draw_engine_eevee_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex_debug, 1);
+ effects->gtao_horizons_debug = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], DRW_TEX_RGBA_8,
+ &draw_engine_eevee_type);
+ GPU_framebuffer_ensure_config(&fbl->gtao_debug_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->gtao_horizons_debug)
+ });
+ }
+ else {
+ effects->gtao_horizons_debug = NULL;
}
return EFFECT_GTAO | EFFECT_NORMAL_BUFFER;
}
/* Cleanup */
- DRW_TEXTURE_FREE_SAFE(txl->gtao_horizons);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->gtao_fb);
+ effects->gtao_horizons = NULL;
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->gtao_fb);
common_data->ao_settings = 0.0f;
return 0;
}
+void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+
+ if (BKE_collection_engine_property_value_get_bool(props, "gtao_enable")) {
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ DRW_texture_ensure_fullscreen_2D(&txl->ao_accum, DRW_TEX_R_32, 0); /* Should be enough precision for many samples. */
+
+ GPU_framebuffer_ensure_config(&fbl->ao_accum_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->ao_accum)
+ });
+
+ /* Clear texture. */
+ GPU_framebuffer_bind(fbl->ao_accum_fb);
+ GPU_framebuffer_clear_color(fbl->ao_accum_fb, clear);
+
+ /* Accumulation pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE;
+ psl->ao_accum_ps = DRW_pass_create("AO Accum", state);
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.gtao_debug_sh, psl->ao_accum_ps);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input);
+ DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ }
+ else {
+ /* Cleanup to release memory */
+ DRW_TEXTURE_FREE_SAFE(txl->ao_accum);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->ao_accum_fb);
+ }
+}
+
void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
@@ -148,16 +202,16 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
psl->ao_horizon_search = DRW_pass_create("GTAO Horizon Search", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.gtao_sh, psl->ao_horizon_search);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &effects->ao_src_depth);
+ DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &effects->ao_src_depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_call_add(grp, quad, NULL);
psl->ao_horizon_search_layer = DRW_pass_create("GTAO Horizon Search Layer", DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(e_data.gtao_layer_sh, psl->ao_horizon_search_layer);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
- DRW_shgroup_uniform_buffer(grp, "depthBufferLayered", &effects->ao_src_depth);
+ DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBufferLayered", &effects->ao_src_depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_int(grp, "layer", &stl->effects->ao_depth_layer, 1);
DRW_shgroup_call_add(grp, quad, NULL);
@@ -166,10 +220,10 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
psl->ao_horizon_debug = DRW_pass_create("GTAO Horizon Debug", DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(e_data.gtao_debug_sh, psl->ao_horizon_debug);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
- DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &txl->gtao_horizons);
+ DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input);
+ DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_call_add(grp, quad, NULL);
}
@@ -189,7 +243,7 @@ void EEVEE_occlusion_compute(
effects->ao_src_depth = depth_src;
effects->ao_depth_layer = layer;
- DRW_framebuffer_bind(fbl->gtao_fb);
+ GPU_framebuffer_bind(fbl->gtao_fb);
if (layer >= 0) {
DRW_draw_pass(psl->ao_horizon_search_layer);
@@ -199,7 +253,7 @@ void EEVEE_occlusion_compute(
}
/* Restore */
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_bind(fbl->main_fb);
DRW_stats_group_end();
}
@@ -215,19 +269,36 @@ void EEVEE_occlusion_draw_debug(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
if (((effects->enabled_effects & EFFECT_GTAO) != 0) && (G.debug_value == 6)) {
DRW_stats_group_start("GTAO Debug");
- DRW_framebuffer_texture_attach(fbl->gtao_debug_fb, stl->g_data->gtao_horizons_debug, 0, 0);
- DRW_framebuffer_bind(fbl->gtao_debug_fb);
-
+ GPU_framebuffer_bind(fbl->gtao_debug_fb);
DRW_draw_pass(psl->ao_horizon_debug);
/* Restore */
- DRW_framebuffer_texture_detach(stl->g_data->gtao_horizons_debug);
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_bind(fbl->main_fb);
DRW_stats_group_end();
}
}
+void EEVEE_occlusion_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_PassList *psl = vedata->psl;
+
+ if (fbl->ao_accum_fb != NULL) {
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ /* Update the min_max/horizon buffers so the refracion materials appear in it. */
+ EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1);
+ EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1);
+
+ GPU_framebuffer_bind(fbl->ao_accum_fb);
+ DRW_draw_pass(psl->ao_accum_ps);
+
+ /* Restore */
+ GPU_framebuffer_bind(fbl->main_fb);
+ }
+}
+
void EEVEE_occlusion_free(void)
{
DRW_SHADER_FREE_SAFE(e_data.gtao_sh);
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 22440fb62c6..d203fadc073 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -29,6 +29,8 @@
struct Object;
struct EEVEE_BoundSphere;
struct EEVEE_ShadowCasterBuffer;
+struct RenderLayer;
+struct RenderResult;
extern struct DrawEngineType draw_engine_eevee_type;
@@ -70,22 +72,23 @@ extern struct DrawEngineType draw_engine_eevee_type;
#define SWAP_DOUBLE_BUFFERS() { \
if (effects->swap_double_buffer) { \
- SWAP(struct GPUFrameBuffer *, fbl->main, fbl->double_buffer); \
+ SWAP(struct GPUFrameBuffer *, fbl->main_fb, fbl->double_buffer_fb); \
+ SWAP(struct GPUFrameBuffer *, fbl->main_color_fb, fbl->double_buffer_color_fb); \
SWAP(GPUTexture *, txl->color, txl->color_double_buffer); \
effects->swap_double_buffer = false; \
} \
} ((void)0)
#define SWAP_BUFFERS() { \
- if (effects->target_buffer != fbl->main) { \
+ if (effects->target_buffer == fbl->effect_color_fb) { \
SWAP_DOUBLE_BUFFERS(); \
effects->source_buffer = txl->color_post; \
- effects->target_buffer = fbl->main; \
+ effects->target_buffer = fbl->main_color_fb; \
} \
else { \
SWAP_DOUBLE_BUFFERS(); \
effects->source_buffer = txl->color; \
- effects->target_buffer = fbl->effect_fb; \
+ effects->target_buffer = fbl->effect_color_fb; \
} \
} ((void)0)
@@ -105,22 +108,22 @@ enum {
VAR_MAT_BLEND = (1 << 4),
VAR_MAT_VSM = (1 << 5),
VAR_MAT_ESM = (1 << 6),
- VAR_MAT_HAIR_FIBERS = (1 << 7),
+ VAR_MAT_VOLUME = (1 << 7),
+ VAR_MAT_HAIR_FIBERS = (1 << 8),
/* Max number of variation */
/* IMPORTANT : Leave it last and set
* it's value accordingly. */
- VAR_MAT_MAX = (1 << 8),
+ VAR_MAT_MAX = (1 << 9),
/* These are options that are not counted in VAR_MAT_MAX
* because they are not cumulative with the others above. */
- VAR_MAT_CLIP = (1 << 9),
- VAR_MAT_HASH = (1 << 10),
- VAR_MAT_MULT = (1 << 11),
- VAR_MAT_SHADOW = (1 << 12),
- VAR_MAT_REFRACT = (1 << 12),
- VAR_MAT_VOLUME = (1 << 13),
- VAR_MAT_SSS = (1 << 14),
- VAR_MAT_TRANSLUC = (1 << 15),
- VAR_MAT_SSSALBED = (1 << 16),
+ VAR_MAT_CLIP = (1 << 10),
+ VAR_MAT_HASH = (1 << 11),
+ VAR_MAT_MULT = (1 << 12),
+ VAR_MAT_SHADOW = (1 << 13),
+ VAR_MAT_REFRACT = (1 << 14),
+ VAR_MAT_SSS = (1 << 15),
+ VAR_MAT_TRANSLUC = (1 << 16),
+ VAR_MAT_SSSALBED = (1 << 17),
};
/* Shadow Technique */
@@ -141,10 +144,8 @@ typedef struct EEVEE_BoundBox {
typedef struct EEVEE_PassList {
/* Shadows */
struct DRWPass *shadow_pass;
- struct DRWPass *shadow_cube_pass;
struct DRWPass *shadow_cube_copy_pass;
struct DRWPass *shadow_cube_store_pass;
- struct DRWPass *shadow_cascade_pass;
struct DRWPass *shadow_cascade_copy_pass;
struct DRWPass *shadow_cascade_store_pass;
@@ -161,6 +162,8 @@ typedef struct EEVEE_PassList {
struct DRWPass *ao_horizon_search;
struct DRWPass *ao_horizon_search_layer;
struct DRWPass *ao_horizon_debug;
+ struct DRWPass *ao_accum_ps;
+ struct DRWPass *mist_accum_ps;
struct DRWPass *motion_blur;
struct DRWPass *bloom_blit;
struct DRWPass *bloom_downsample_first;
@@ -179,6 +182,7 @@ typedef struct EEVEE_PassList {
struct DRWPass *ssr_resolve;
struct DRWPass *sss_blur_ps;
struct DRWPass *sss_resolve_ps;
+ struct DRWPass *sss_accum_ps;
struct DRWPass *color_downsample_ps;
struct DRWPass *color_downsample_cube_ps;
struct DRWPass *taa_resolve;
@@ -215,12 +219,13 @@ typedef struct EEVEE_FramebufferList {
struct GPUFrameBuffer *gtao_fb;
struct GPUFrameBuffer *gtao_debug_fb;
struct GPUFrameBuffer *downsample_fb;
- struct GPUFrameBuffer *effect_fb;
struct GPUFrameBuffer *bloom_blit_fb;
struct GPUFrameBuffer *bloom_down_fb[MAX_BLOOM_STEP];
struct GPUFrameBuffer *bloom_accum_fb[MAX_BLOOM_STEP - 1];
struct GPUFrameBuffer *sss_blur_fb;
+ struct GPUFrameBuffer *sss_resolve_fb;
struct GPUFrameBuffer *sss_clear_fb;
+ struct GPUFrameBuffer *sss_accum_fb;
struct GPUFrameBuffer *dof_down_fb;
struct GPUFrameBuffer *dof_scatter_far_fb;
struct GPUFrameBuffer *dof_scatter_near_fb;
@@ -229,30 +234,30 @@ typedef struct EEVEE_FramebufferList {
struct GPUFrameBuffer *volumetric_integ_fb;
struct GPUFrameBuffer *screen_tracing_fb;
struct GPUFrameBuffer *refract_fb;
+ struct GPUFrameBuffer *mist_accum_fb;
+ struct GPUFrameBuffer *ao_accum_fb;
struct GPUFrameBuffer *update_noise_fb;
struct GPUFrameBuffer *planarref_fb;
+ struct GPUFrameBuffer *planar_downsample_fb;
- struct GPUFrameBuffer *main;
- struct GPUFrameBuffer *double_buffer;
- struct GPUFrameBuffer *depth_double_buffer_fb;
+ struct GPUFrameBuffer *main_fb;
+ struct GPUFrameBuffer *main_color_fb;
+ struct GPUFrameBuffer *effect_fb;
+ struct GPUFrameBuffer *effect_color_fb;
+ struct GPUFrameBuffer *double_buffer_fb;
+ struct GPUFrameBuffer *double_buffer_color_fb;
+ struct GPUFrameBuffer *double_buffer_depth_fb;
} EEVEE_FramebufferList;
typedef struct EEVEE_TextureList {
/* Effects */
struct GPUTexture *color_post; /* R16_G16_B16 */
- struct GPUTexture *dof_down_near; /* R16_G16_B16_A16 */
- struct GPUTexture *dof_down_far; /* R16_G16_B16_A16 */
- struct GPUTexture *dof_coc; /* R16_G16 */
- struct GPUTexture *dof_near_blur; /* R16_G16_B16_A16 */
- struct GPUTexture *dof_far_blur; /* R16_G16_B16_A16 */
- struct GPUTexture *bloom_blit; /* R16_G16_B16 */
- struct GPUTexture *bloom_downsample[MAX_BLOOM_STEP]; /* R16_G16_B16 */
- struct GPUTexture *bloom_upsample[MAX_BLOOM_STEP - 1]; /* R16_G16_B16 */
- struct GPUTexture *ssr_normal_input;
- struct GPUTexture *ssr_specrough_input;
- struct GPUTexture *ssr_hit_output;
+ struct GPUTexture *mist_accum;
+ struct GPUTexture *ao_accum;
+ struct GPUTexture *sss_dir_accum;
+ struct GPUTexture *sss_col_accum;
struct GPUTexture *refract_color;
struct GPUTexture *volume_prop_scattering;
@@ -267,13 +272,6 @@ typedef struct EEVEE_TextureList {
struct GPUTexture *planar_pool;
struct GPUTexture *planar_depth;
- struct GPUTexture *gtao_horizons;
-
- struct GPUTexture *sss_data;
- struct GPUTexture *sss_albedo;
- struct GPUTexture *sss_blur;
- struct GPUTexture *sss_stencil;
-
struct GPUTexture *maxzbuffer;
struct GPUTexture *color; /* R16_G16_B16 */
@@ -356,6 +354,7 @@ typedef struct EEVEE_LampsInfo {
int shadow_cube_target_size;
int current_shadow_cascade;
int current_shadow_face;
+ unsigned int shadow_instance_count;
float filter_size;
/* List of lights in the scene. */
/* XXX This is fragile, can get out of sync quickly. */
@@ -431,7 +430,10 @@ typedef struct EEVEE_LightProbesInfo {
int target_size;
int grid_initialized;
struct World *prev_world;
+ int update_world;
+ bool prev_wo_sh_compiled;
bool do_cube_update;
+ bool all_materials_updated;
/* For rendering probes */
float probemat[6][4][4];
int layer;
@@ -467,18 +469,42 @@ enum {
};
/* ************ EFFECTS DATA ************* */
+
+typedef enum EEVEE_EffectsFlag {
+ EFFECT_MOTION_BLUR = (1 << 0),
+ EFFECT_BLOOM = (1 << 1),
+ EFFECT_DOF = (1 << 2),
+ EFFECT_VOLUMETRIC = (1 << 3),
+ EFFECT_SSR = (1 << 4),
+ EFFECT_DOUBLE_BUFFER = (1 << 5), /* Not really an effect but a feature */
+ EFFECT_REFRACT = (1 << 6),
+ EFFECT_GTAO = (1 << 7),
+ EFFECT_TAA = (1 << 8),
+ EFFECT_POST_BUFFER = (1 << 9), /* Not really an effect but a feature */
+ EFFECT_NORMAL_BUFFER = (1 << 10), /* Not really an effect but a feature */
+ EFFECT_SSS = (1 << 11),
+} EEVEE_EffectsFlag;
+
typedef struct EEVEE_EffectsInfo {
- int enabled_effects;
+ EEVEE_EffectsFlag enabled_effects;
bool swap_double_buffer;
/* SSSS */
int sss_sample_count;
bool sss_separate_albedo;
+ struct GPUTexture *sss_data; /* Textures from pool */
+ struct GPUTexture *sss_albedo;
+ struct GPUTexture *sss_blur;
+ struct GPUTexture *sss_stencil;
/* Volumetrics */
int volume_current_sample;
/* SSR */
bool reflection_trace_full;
int ssr_neighbor_ofs;
int ssr_halfres_ofs[2];
+ struct GPUTexture *ssr_normal_input; /* Textures from pool */
+ struct GPUTexture *ssr_specrough_input;
+ struct GPUTexture *ssr_hit_output;
+ struct GPUTexture *ssr_pdf_output;
/* Temporal Anti Aliasing */
int taa_current_sample;
int taa_render_sample;
@@ -493,6 +519,8 @@ typedef struct EEVEE_EffectsInfo {
/* Ambient Occlusion */
int ao_depth_layer;
struct GPUTexture *ao_src_depth; /* pointer copy */
+ struct GPUTexture *gtao_horizons; /* Textures from pool */
+ struct GPUTexture *gtao_horizons_debug;
/* Motion Blur */
float current_ndc_to_world[4][4];
float past_world_to_ndc[4][4];
@@ -503,6 +531,13 @@ typedef struct EEVEE_EffectsInfo {
float dof_bokeh[4];
float dof_layer_select[2];
int dof_target_size[2];
+ struct GPUTexture *dof_down_near; /* Textures from pool */
+ struct GPUTexture *dof_down_far;
+ struct GPUTexture *dof_coc;
+ struct GPUTexture *dof_near_blur;
+ struct GPUTexture *dof_far_blur;
+ /* Other */
+ float prev_persmat[4][4];
/* Bloom */
int bloom_iteration_ct;
float source_texel_size[2];
@@ -513,28 +548,18 @@ typedef struct EEVEE_EffectsInfo {
float bloom_sample_scale;
float bloom_curve_threshold[4];
float unf_source_texel_size[2];
+ struct GPUTexture *bloom_blit; /* Textures from pool */
+ struct GPUTexture *bloom_downsample[MAX_BLOOM_STEP];
+ struct GPUTexture *bloom_upsample[MAX_BLOOM_STEP - 1];
struct GPUTexture *unf_source_buffer; /* pointer copy */
struct GPUTexture *unf_base_buffer; /* pointer copy */
/* Not alloced, just a copy of a *GPUtexture in EEVEE_TextureList. */
struct GPUTexture *source_buffer; /* latest updated texture */
struct GPUFrameBuffer *target_buffer; /* next target to render to */
+ struct GPUTexture *final_tx; /* Final color to transform to display color space. */
+ struct GPUFrameBuffer *final_fb; /* Framebuffer with final_tx as attachement. */
} EEVEE_EffectsInfo;
-enum {
- EFFECT_MOTION_BLUR = (1 << 0),
- EFFECT_BLOOM = (1 << 1),
- EFFECT_DOF = (1 << 2),
- EFFECT_VOLUMETRIC = (1 << 3),
- EFFECT_SSR = (1 << 4),
- EFFECT_DOUBLE_BUFFER = (1 << 5), /* Not really an effect but a feature */
- EFFECT_REFRACT = (1 << 6),
- EFFECT_GTAO = (1 << 7),
- EFFECT_TAA = (1 << 8),
- EFFECT_POST_BUFFER = (1 << 9), /* Not really an effect but a feature */
- EFFECT_NORMAL_BUFFER = (1 << 10), /* Not really an effect but a feature */
- EFFECT_SSS = (1 << 11),
-};
-
/* ***************** COMMON DATA **************** */
/* Common uniform buffer containing all "constant" data over the whole drawing pipeline. */
@@ -587,6 +612,12 @@ typedef struct EEVEE_CommonUniformBuffer {
float prb_lod_planar_max; /* float */
} EEVEE_CommonUniformBuffer;
+/* ***************** CLIP PLANES DATA **************** */
+
+typedef struct EEVEE_ClipPlanesUniformBuffer {
+ float clip_planes[1][4]; /* must be less than MAX_CLIP_PLANES */
+} EEVEE_ClipPlanesUniformBuffer;
+
/* ************** SCENE LAYER DATA ************** */
typedef struct EEVEE_ViewLayerData {
/* Lamps */
@@ -597,7 +628,8 @@ typedef struct EEVEE_ViewLayerData {
struct GPUUniformBuffer *shadow_render_ubo;
struct GPUUniformBuffer *shadow_samples_ubo;
- struct GPUFrameBuffer *shadow_target_fb;
+ struct GPUFrameBuffer *shadow_cube_target_fb;
+ struct GPUFrameBuffer *shadow_cascade_target_fb;
struct GPUFrameBuffer *shadow_store_fb;
struct GPUTexture *shadow_cube_target;
@@ -615,8 +647,8 @@ typedef struct EEVEE_ViewLayerData {
struct GPUUniformBuffer *grid_ubo;
struct GPUUniformBuffer *planar_ubo;
- struct GPUFrameBuffer *probe_fb;
struct GPUFrameBuffer *probe_filter_fb;
+ struct GPUFrameBuffer *probe_face_fb[6];
struct GPUTexture *probe_rt;
struct GPUTexture *probe_depth_rt;
@@ -627,6 +659,9 @@ typedef struct EEVEE_ViewLayerData {
/* Common Uniform Buffer */
struct EEVEE_CommonUniformBuffer common_data;
struct GPUUniformBuffer *common_ubo;
+
+ struct EEVEE_ClipPlanesUniformBuffer clip_data;
+ struct GPUUniformBuffer *clip_ubo;
} EEVEE_ViewLayerData;
/* ************ OBJECT DATA ************ */
@@ -641,6 +676,7 @@ typedef struct EEVEE_ShadowCubeData {
typedef struct EEVEE_ShadowCascadeData {
short light_id, shadow_id, cascade_id, layer_id;
float viewprojmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */
+ DRWMatrixState clipmat; /* Override matrices used for clipping. */
float radius[MAX_CASCADE_NUM];
} EEVEE_ShadowCascadeData;
@@ -648,6 +684,8 @@ typedef struct EEVEE_ShadowCascadeData {
* It works with even if the object is in multiple layers
* because we don't get the same "Object *" for each layer. */
typedef struct EEVEE_LampEngineData {
+ ObjectEngineData engine_data;
+
bool need_update;
/* This needs to be out of the union to avoid undefined behaviour. */
short prev_cube_shadow_id;
@@ -659,6 +697,8 @@ typedef struct EEVEE_LampEngineData {
} EEVEE_LampEngineData;
typedef struct EEVEE_LightProbeEngineData {
+ ObjectEngineData engine_data;
+
/* NOTE: need_full_update is set by dependency graph when the probe or it's
* object is updated. This triggers full probe update, including it's
* "progressive" GI refresh.
@@ -679,14 +719,14 @@ typedef struct EEVEE_LightProbeEngineData {
int max_lvl;
int probe_id; /* Only used for display data */
float probe_size; /* Only used for display data */
- /* For planar reflection rendering */
- float viewmat[4][4];
- float persmat[4][4];
+ DRWMatrixState mats; /* For planar probes */
float planer_eq_offset[4];
struct ListBase captured_object_list;
} EEVEE_LightProbeEngineData;
typedef struct EEVEE_ObjectEngineData {
+ ObjectEngineData engine_data;
+
bool need_update;
unsigned int shadow_caster_id;
} EEVEE_ObjectEngineData;
@@ -717,18 +757,20 @@ typedef struct EEVEE_PrivateData {
struct DRWShadingGroup *refract_depth_shgrp_clip_cull;
struct DRWShadingGroup *cube_display_shgrp;
struct DRWShadingGroup *planar_display_shgrp;
- struct DRWShadingGroup *planar_downsample;
struct GHash *material_hash;
struct GHash *hair_material_hash;
- struct GPUTexture *minzbuffer;
- struct GPUTexture *ssr_pdf_output;
- struct GPUTexture *gtao_horizons_debug;
float background_alpha; /* TODO find a better place for this. */
/* For planar probes */
float planar_texel_size[2];
/* For double buffering */
bool view_updated;
bool valid_double_buffer;
+ /* Render Matrices */
+ float persmat[4][4], persinv[4][4];
+ float viewmat[4][4], viewinv[4][4];
+ float winmat[4][4], wininv[4][4];
+ /* Mist Settings */
+ float mist_start, mist_inv_dist, mist_falloff;
} EEVEE_PrivateData; /* Transient data */
/* eevee_data.c */
@@ -744,7 +786,7 @@ EEVEE_LampEngineData *EEVEE_lamp_data_ensure(Object *ob);
/* eevee_materials.c */
struct GPUTexture *EEVEE_materials_get_util_tex(void); /* XXX */
void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl);
-void EEVEE_materials_cache_init(EEVEE_Data *vedata);
+void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob);
void EEVEE_materials_cache_finish(EEVEE_Data *vedata);
struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, struct World *wo);
@@ -758,14 +800,14 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, Material
struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma, int shadow_method, bool use_fibers);
void EEVEE_materials_free(void);
void EEVEE_draw_default_passes(EEVEE_PassList *psl);
-void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, double offsets[3]);
+void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const double offsets[3]);
/* eevee_lights.c */
void EEVEE_lights_init(EEVEE_ViewLayerData *sldata);
-void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl);
+void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, struct Object *ob);
void EEVEE_lights_cache_shcaster_add(
- EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl, struct Gwn_Batch *geom, float (*obmat)[4]);
+ EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, struct Gwn_Batch *geom, Object *ob);
void EEVEE_lights_cache_shcaster_material_add(
EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl,
struct GPUMaterial *gpumat, struct Gwn_Batch *geom, struct Object *ob,
@@ -777,15 +819,17 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl);
void EEVEE_lights_free(void);
/* eevee_lightprobes.c */
+bool EEVEE_lightprobes_all_probes_ready(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob);
void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_lightprobes_free(void);
/* eevee_depth_of_field.c */
-int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera);
void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_depth_of_field_draw(EEVEE_Data *vedata);
void EEVEE_depth_of_field_free(void);
@@ -798,6 +842,8 @@ void EEVEE_bloom_free(void);
/* eevee_occlusion.c */
int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_occlusion_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_occlusion_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer);
void EEVEE_occlusion_draw_debug(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
@@ -813,26 +859,36 @@ void EEVEE_screen_raytrace_free(void);
/* eevee_subsurface.c */
int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_add_pass(
EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile);
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_free(void);
/* eevee_motion_blur.c */
-int EEVEE_motion_blur_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+int EEVEE_motion_blur_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera);
void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_motion_blur_draw(EEVEE_Data *vedata);
void EEVEE_motion_blur_free(void);
+/* eevee_mist.c */
+void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_mist_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);;
+void EEVEE_mist_free(void);
+
/* eevee_temporal_sampling.c */
int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_temporal_sampling_matrices_calc(
+ EEVEE_EffectsInfo *effects, float viewmat[4][4], float persmat[4][4], const double ht_point[2]);
void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata);
void EEVEE_temporal_sampling_free(void);
/* eevee_volumes.c */
int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, unsigned int current_sample);
void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct Scene *scene, Object *ob);
void EEVEE_volumes_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
@@ -841,15 +897,21 @@ void EEVEE_volumes_free_smoke_textures(void);
void EEVEE_volumes_free(void);
/* eevee_effects.c */
-void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera);
void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer);
-void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, struct GPUTexture *texture_src, int level);
-void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, struct GPUTexture *texture_src, int level);
+void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUTexture *texture_src, int level);
+void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUTexture *texture_src, int level);
void EEVEE_effects_do_gtao(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_effects_free(void);
+/* eevee_render.c */
+void EEVEE_render_init(EEVEE_Data *vedata, struct RenderEngine *engine, struct Depsgraph *depsgraph);
+void EEVEE_render_cache(void *vedata, struct Object *ob, struct RenderEngine *engine, struct Depsgraph *depsgraph);
+void EEVEE_render_draw(EEVEE_Data *vedata, struct RenderEngine *engine, struct RenderLayer *render_layer, const struct rcti *rect);
+void EEVEE_render_update_passes(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer);
+
/* Shadow Matrix */
static const float texcomat[4][4] = { /* From NDC to TexCo */
{0.5f, 0.0f, 0.0f, 0.0f},
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
new file mode 100644
index 00000000000..130999adb39
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -0,0 +1,562 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file eevee_render.c
+ * \ingroup draw_engine
+ */
+
+/**
+ * Render functions for final render outputs.
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_rand.h"
+#include "BLI_rect.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "GPU_framebuffer.h"
+#include "GPU_glew.h"
+
+#include "RE_pipeline.h"
+
+#include "eevee_private.h"
+
+void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *depsgraph)
+{
+ EEVEE_Data *vedata = (EEVEE_Data *)ved;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+
+ /* Init default FB and render targets:
+ * In render mode the default framebuffer is not generated
+ * because there is no viewport. So we need to manually create it or
+ * not use it. For code clarity we just allocate it make use of it. */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ /* TODO 32 bit depth */
+ DRW_texture_ensure_fullscreen_2D(&dtxl->depth, DRW_TEX_DEPTH_24_STENCIL_8, 0);
+ DRW_texture_ensure_fullscreen_2D(&txl->color, DRW_TEX_RGBA_32, DRW_TEX_FILTER | DRW_TEX_MIPMAP);
+
+ GPU_framebuffer_ensure_config(&dfbl->default_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(txl->color)
+ });
+ GPU_framebuffer_ensure_config(&fbl->main_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(txl->color)
+ });
+ GPU_framebuffer_ensure_config(&fbl->main_color_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->color)
+ });
+
+ /* Alloc transient data. */
+ if (!stl->g_data) {
+ stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
+ }
+ EEVEE_PrivateData *g_data = stl->g_data;
+ g_data->background_alpha = DRW_state_draw_background() ? 1.0f : 0.0f;
+ g_data->valid_double_buffer = 0;
+
+ /* Alloc common ubo data. */
+ if (sldata->common_ubo == NULL) {
+ sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), &sldata->common_data);
+ }
+ if (sldata->clip_ubo == NULL) {
+ sldata->clip_ubo = DRW_uniformbuffer_create(sizeof(sldata->clip_data), &sldata->clip_data);
+ }
+
+ /* Set the pers & view matrix. */
+ /* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */
+ struct Object *camera = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
+ float frame = BKE_scene_frame_get(scene);
+ RE_GetCameraWindow(engine->re, camera, frame, g_data->winmat);
+ RE_GetCameraModelMatrix(engine->re, camera, g_data->viewinv);
+
+ invert_m4_m4(g_data->viewmat, g_data->viewinv);
+ mul_m4_m4m4(g_data->persmat, g_data->winmat, g_data->viewmat);
+ invert_m4_m4(g_data->persinv, g_data->persmat);
+ invert_m4_m4(g_data->wininv, g_data->winmat);
+
+ DRW_viewport_matrix_override_set(g_data->persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_override_set(g_data->persinv, DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_set(g_data->winmat, DRW_MAT_WIN);
+ DRW_viewport_matrix_override_set(g_data->wininv, DRW_MAT_WININV);
+ DRW_viewport_matrix_override_set(g_data->viewmat, DRW_MAT_VIEW);
+ DRW_viewport_matrix_override_set(g_data->viewinv, DRW_MAT_VIEWINV);
+
+ /* EEVEE_effects_init needs to go first for TAA */
+ EEVEE_effects_init(sldata, vedata, camera);
+ EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_lights_init(sldata);
+ EEVEE_lightprobes_init(sldata, vedata);
+
+ /* INIT CACHE */
+ EEVEE_bloom_cache_init(sldata, vedata);
+ EEVEE_depth_of_field_cache_init(sldata, vedata);
+ EEVEE_effects_cache_init(sldata, vedata);
+ EEVEE_lightprobes_cache_init(sldata, vedata);
+ EEVEE_lights_cache_init(sldata, vedata);
+ EEVEE_materials_cache_init(sldata, vedata);
+ EEVEE_motion_blur_cache_init(sldata, vedata);
+ EEVEE_occlusion_cache_init(sldata, vedata);
+ EEVEE_screen_raytrace_cache_init(sldata, vedata);
+ EEVEE_subsurface_cache_init(sldata, vedata);
+ EEVEE_temporal_sampling_cache_init(sldata, vedata);
+ EEVEE_volumes_cache_init(sldata, vedata);
+}
+
+void EEVEE_render_cache(
+ void *vedata, struct Object *ob,
+ struct RenderEngine *engine, struct Depsgraph *UNUSED(depsgraph))
+{
+ EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
+
+ char info[42];
+ BLI_snprintf(info, sizeof(info), "Syncing %s", ob->id.name + 2);
+ RE_engine_update_stats(engine, NULL, info);
+
+ if (DRW_check_object_visible_within_active_context(ob) == false) {
+ return;
+ }
+
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
+ EEVEE_materials_cache_populate(vedata, sldata, ob);
+
+ const bool cast_shadow = true;
+
+ if (cast_shadow) {
+ EEVEE_lights_cache_shcaster_object_add(sldata, ob);
+ }
+ }
+ else if (ob->type == OB_LIGHTPROBE) {
+ EEVEE_lightprobes_cache_add(sldata, ob);
+ }
+ else if (ob->type == OB_LAMP) {
+ EEVEE_lights_cache_add(sldata, ob);
+ }
+}
+
+static void eevee_render_result_combined(
+ RenderLayer *rl, const char *viewname, const rcti *rect,
+ EEVEE_Data *vedata, EEVEE_ViewLayerData *UNUSED(sldata))
+{
+ RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname);
+
+ GPU_framebuffer_bind(vedata->stl->effects->final_fb);
+ GPU_framebuffer_read_color(vedata->stl->effects->final_fb,
+ rect->xmin, rect->ymin,
+ BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
+ 4, 0, rp->rect);
+}
+
+static void eevee_render_result_subsurface(
+ RenderLayer *rl, const char *viewname, const rcti *rect,
+ EEVEE_Data *vedata, EEVEE_ViewLayerData *UNUSED(sldata), int render_samples)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+
+ if (vedata->fbl->sss_accum_fb == NULL) {
+ /* SSS is not enabled. */
+ return;
+ }
+
+ if ((view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR) != 0) {
+ RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_SUBSURFACE_COLOR, viewname);
+
+ GPU_framebuffer_bind(vedata->fbl->sss_accum_fb);
+ GPU_framebuffer_read_color(vedata->fbl->sss_accum_fb,
+ rect->xmin, rect->ymin,
+ BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
+ 3, 1, rp->rect);
+
+ /* This is the accumulated color. Divide by the number of samples. */
+ for (int i = 0; i < rp->rectx * rp->recty * 3; i++) {
+ rp->rect[i] /= (float)render_samples;
+ }
+ }
+
+ if ((view_layer->passflag & SCE_PASS_SUBSURFACE_DIRECT) != 0) {
+ RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_SUBSURFACE_DIRECT, viewname);
+
+ GPU_framebuffer_bind(vedata->fbl->sss_accum_fb);
+ GPU_framebuffer_read_color(vedata->fbl->sss_accum_fb,
+ rect->xmin, rect->ymin,
+ BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
+ 3, 0, rp->rect);
+
+ /* This is the accumulated color. Divide by the number of samples. */
+ for (int i = 0; i < rp->rectx * rp->recty * 3; i++) {
+ rp->rect[i] /= (float)render_samples;
+ }
+ }
+
+ if ((view_layer->passflag & SCE_PASS_SUBSURFACE_INDIRECT) != 0) {
+ /* Do nothing as all the lighting is in the direct pass.
+ * TODO : Separate Direct from indirect lighting. */
+ }
+}
+
+static void eevee_render_result_normal(
+ RenderLayer *rl, const char *viewname, const rcti *rect,
+ EEVEE_Data *vedata, EEVEE_ViewLayerData *UNUSED(sldata))
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_PrivateData *g_data = stl->g_data;
+
+ /* Only read the center texel. */
+ if (stl->effects->taa_current_sample > 1)
+ return;
+
+ if ((view_layer->passflag & SCE_PASS_NORMAL) != 0) {
+ RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_NORMAL, viewname);
+
+ GPU_framebuffer_bind(vedata->fbl->main_fb);
+ GPU_framebuffer_read_color(vedata->fbl->main_fb,
+ rect->xmin, rect->ymin,
+ BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
+ 3, 1, rp->rect);
+
+ /* Convert Eevee encoded normals to Blender normals. */
+ for (int i = 0; i < rp->rectx * rp->recty * 3; i += 3) {
+ if (rp->rect[i] == 0.0f && rp->rect[i + 1] == 0.0f) {
+ /* If normal is not correct then do not produce NANs. */
+ continue;
+ }
+
+ float fenc[2];
+ fenc[0] = rp->rect[i+0] * 4.0f - 2.0f;
+ fenc[1] = rp->rect[i+1] * 4.0f - 2.0f;
+
+ float f = dot_v2v2(fenc, fenc);
+ float g = sqrtf(1.0f - f / 4.0f);
+
+ rp->rect[i + 0] = fenc[0] * g;
+ rp->rect[i + 1] = fenc[1] * g;
+ rp->rect[i + 2] = 1.0f - f / 2.0f;
+
+ mul_mat3_m4_v3(g_data->viewinv, &rp->rect[i]);
+ }
+ }
+}
+
+static void eevee_render_result_z(
+ RenderLayer *rl, const char *viewname, const rcti *rect,
+ EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_PrivateData *g_data = stl->g_data;
+
+ /* Only read the center texel. */
+ if (stl->effects->taa_current_sample > 1)
+ return;
+
+ if ((view_layer->passflag & SCE_PASS_Z) != 0) {
+ RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname);
+
+ GPU_framebuffer_read_depth(vedata->fbl->main_fb,
+ rect->xmin, rect->ymin,
+ BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
+ rp->rect);
+
+ bool is_persp = DRW_viewport_is_persp_get();
+
+ /* Convert ogl depth [0..1] to view Z [near..far] */
+ for (int i = 0; i < rp->rectx * rp->recty; ++i) {
+ if (rp->rect[i] == 1.0f ) {
+ rp->rect[i] = 1e10f; /* Background */
+ }
+ else {
+ if (is_persp) {
+ rp->rect[i] = rp->rect[i] * 2.0f - 1.0f;
+ rp->rect[i] = g_data->winmat[3][2] / (rp->rect[i] + g_data->winmat[2][2]);
+ }
+ else {
+ rp->rect[i] = -common_data->view_vecs[0][2] + rp->rect[i] * -common_data->view_vecs[1][2];
+ }
+ }
+ }
+ }
+}
+
+static void eevee_render_result_mist(
+ RenderLayer *rl, const char *viewname, const rcti *rect,
+ EEVEE_Data *vedata, EEVEE_ViewLayerData *UNUSED(sldata), int render_samples)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+
+ if ((view_layer->passflag & SCE_PASS_MIST) != 0) {
+ RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_MIST, viewname);
+
+ GPU_framebuffer_bind(vedata->fbl->mist_accum_fb);
+ GPU_framebuffer_read_color(vedata->fbl->mist_accum_fb,
+ rect->xmin, rect->ymin,
+ BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
+ 1, 0, rp->rect);
+
+ /* This is the accumulated color. Divide by the number of samples. */
+ for (int i = 0; i < rp->rectx * rp->recty; i++) {
+ rp->rect[i] /= (float)render_samples;
+ }
+ }
+}
+
+static void eevee_render_result_occlusion(
+ RenderLayer *rl, const char *viewname, const rcti *rect,
+ EEVEE_Data *vedata, EEVEE_ViewLayerData *UNUSED(sldata), int render_samples)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+
+ if (vedata->fbl->ao_accum_fb == NULL) {
+ /* AO is not enabled. */
+ return;
+ }
+
+ if ((view_layer->passflag & SCE_PASS_AO) != 0) {
+ RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_AO, viewname);
+
+ GPU_framebuffer_bind(vedata->fbl->ao_accum_fb);
+ GPU_framebuffer_read_color(vedata->fbl->ao_accum_fb,
+ rect->xmin, rect->ymin,
+ BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
+ 3, 0, rp->rect);
+
+ /* This is the accumulated color. Divide by the number of samples. */
+ for (int i = 0; i < rp->rectx * rp->recty * 3; i += 3) {
+ rp->rect[i] = rp->rect[i + 1] = rp->rect[i+2] = min_ff(1.0f, rp->rect[i] / (float)render_samples);
+ }
+ }
+}
+
+static void eevee_render_draw_background(EEVEE_Data *vedata)
+{
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_PassList *psl = vedata->psl;
+
+ /* Prevent background to write to data buffers.
+ * NOTE : This also make sure the textures are bound
+ * to the right double buffer. */
+ GPU_framebuffer_ensure_config(&fbl->main_fb, {
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_NONE
+ });
+ GPU_framebuffer_bind(fbl->main_fb);
+
+ DRW_draw_pass(psl->background_pass);
+
+ GPU_framebuffer_ensure_config(&fbl->main_fb, {
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_TEXTURE(stl->effects->ssr_normal_input),
+ GPU_ATTACHMENT_TEXTURE(stl->effects->ssr_specrough_input),
+ GPU_ATTACHMENT_TEXTURE(stl->effects->sss_data),
+ GPU_ATTACHMENT_TEXTURE(stl->effects->sss_albedo)
+ });
+ GPU_framebuffer_bind(fbl->main_fb);
+}
+
+void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl, const rcti *rect)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ const char *viewname = RE_GetActiveRenderView(engine->re);
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
+ EEVEE_PrivateData *g_data = stl->g_data;
+
+ /* FINISH CACHE */
+ EEVEE_materials_cache_finish(vedata);
+ EEVEE_lights_cache_finish(sldata);
+ EEVEE_lightprobes_cache_finish(sldata, vedata);
+
+ /* Sort transparents before the loop. */
+ DRW_pass_sort_shgroup_z(psl->transparent_pass);
+
+ /* Push instances attribs to the GPU. */
+ DRW_render_instance_buffer_finish();
+
+ if ((view_layer->passflag & (SCE_PASS_SUBSURFACE_COLOR |
+ SCE_PASS_SUBSURFACE_DIRECT |
+ SCE_PASS_SUBSURFACE_INDIRECT)) != 0)
+ {
+ EEVEE_subsurface_output_init(sldata, vedata);
+ }
+
+ if ((view_layer->passflag & SCE_PASS_MIST) != 0) {
+ EEVEE_mist_output_init(sldata, vedata);
+ }
+
+ if ((view_layer->passflag & SCE_PASS_AO) != 0) {
+ EEVEE_occlusion_output_init(sldata, vedata);
+ }
+
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+ unsigned int tot_sample = BKE_collection_engine_property_value_get_int(props, "taa_render_samples");
+ unsigned int render_samples = 0;
+
+ if (RE_engine_test_break(engine)) {
+ return;
+ }
+
+ while (render_samples < tot_sample && !RE_engine_test_break(engine)) {
+ float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float clear_depth = 1.0f;
+ unsigned int clear_stencil = 0xFF;
+ unsigned int primes[3] = {2, 3, 7};
+ double offset[3] = {0.0, 0.0, 0.0};
+ double r[3];
+
+ /* Restore winmat before jittering again. */
+ copy_m4_m4(stl->effects->overide_winmat, g_data->winmat);
+ /* Copy previous persmat to UBO data */
+ copy_m4_m4(sldata->common_data.prev_persmat, stl->effects->prev_persmat);
+
+ BLI_halton_3D(primes, offset, stl->effects->taa_current_sample, r);
+ EEVEE_update_noise(psl, fbl, r);
+ EEVEE_temporal_sampling_matrices_calc(stl->effects, g_data->viewmat, g_data->persmat, r);
+ EEVEE_volumes_set_jitter(sldata, stl->effects->taa_current_sample - 1);
+ EEVEE_materials_init(sldata, stl, fbl);
+
+ /* Set matrices. */
+ DRW_viewport_matrix_override_set(stl->effects->overide_persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_override_set(stl->effects->overide_persinv, DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_set(stl->effects->overide_winmat, DRW_MAT_WIN);
+ DRW_viewport_matrix_override_set(stl->effects->overide_wininv, DRW_MAT_WININV);
+ DRW_viewport_matrix_override_set(g_data->viewmat, DRW_MAT_VIEW);
+ DRW_viewport_matrix_override_set(g_data->viewinv, DRW_MAT_VIEWINV);
+
+ /* Refresh Probes */
+ while (EEVEE_lightprobes_all_probes_ready(sldata, vedata) == false) {
+ RE_engine_update_stats(engine, NULL, "Updating Probes");
+ EEVEE_lightprobes_refresh(sldata, vedata);
+ /* Refreshing probes can take some times, allow exit. */
+ if (RE_engine_test_break(engine)) {
+ return;
+ }
+ }
+ EEVEE_lightprobes_refresh_planar(sldata, vedata);
+ DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
+
+ char info[42];
+ BLI_snprintf(info, sizeof(info), "Rendering %u / %u samples", render_samples+1, tot_sample);
+ RE_engine_update_stats(engine, NULL, info);
+
+ /* Refresh Shadows */
+ EEVEE_draw_shadows(sldata, psl);
+
+ GPU_framebuffer_bind(fbl->main_fb);
+ GPU_framebuffer_clear_color_depth_stencil(fbl->main_fb, clear_col, clear_depth, clear_stencil);
+ /* Depth prepass */
+ DRW_draw_pass(psl->depth_pass);
+ DRW_draw_pass(psl->depth_pass_cull);
+ /* Create minmax texture */
+ EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1);
+ EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1);
+ EEVEE_volumes_compute(sldata, vedata);
+ /* Shading pass */
+ eevee_render_draw_background(vedata);
+ GPU_framebuffer_bind(fbl->main_fb);
+ EEVEE_draw_default_passes(psl);
+ DRW_draw_pass(psl->material_pass);
+ EEVEE_subsurface_data_render(sldata, vedata);
+ /* Effects pre-transparency */
+ EEVEE_subsurface_compute(sldata, vedata);
+ EEVEE_reflection_compute(sldata, vedata);
+ EEVEE_refraction_compute(sldata, vedata);
+ /* Opaque refraction */
+ DRW_draw_pass(psl->refract_depth_pass);
+ DRW_draw_pass(psl->refract_depth_pass_cull);
+ DRW_draw_pass(psl->refract_pass);
+ /* Subsurface output */
+ EEVEE_subsurface_output_accumulate(sldata, vedata);
+ /* Occlusion output */
+ EEVEE_occlusion_output_accumulate(sldata, vedata);
+ /* Result NORMAL */
+ eevee_render_result_normal(rl, viewname, rect, vedata, sldata);
+ /* Volumetrics Resolve Opaque */
+ EEVEE_volumes_resolve(sldata, vedata);
+ /* Mist output */
+ EEVEE_mist_output_accumulate(sldata, vedata);
+ /* Transparent */
+ DRW_draw_pass(psl->transparent_pass);
+ /* Result Z */
+ eevee_render_result_z(rl, viewname, rect, vedata, sldata);
+ /* Post Process */
+ EEVEE_draw_effects(sldata, vedata);
+
+ RE_engine_update_progress(engine, (float)(render_samples++) / (float)tot_sample);
+ }
+
+ eevee_render_result_combined(rl, viewname, rect, vedata, sldata);
+ eevee_render_result_subsurface(rl, viewname, rect, vedata, sldata, render_samples);
+ eevee_render_result_mist(rl, viewname, rect, vedata, sldata, render_samples);
+ eevee_render_result_occlusion(rl, viewname, rect, vedata, sldata, render_samples);
+}
+
+void EEVEE_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer)
+{
+ int type;
+
+ RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA);
+
+#define CHECK_PASS(name, channels, chanid) \
+ if (view_layer->passflag & (SCE_PASS_ ## name)) { \
+ if (channels == 4) type = SOCK_RGBA; \
+ else if (channels == 3) type = SOCK_VECTOR; \
+ else type = SOCK_FLOAT; \
+ RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_ ## name, channels, chanid, type); \
+ }
+
+ CHECK_PASS(Z, 1, "Z");
+ CHECK_PASS(MIST, 1, "Z");
+ CHECK_PASS(NORMAL, 3, "XYZ");
+ CHECK_PASS(AO, 3, "RGB");
+ CHECK_PASS(SUBSURFACE_COLOR, 3, "RGB");
+ CHECK_PASS(SUBSURFACE_DIRECT, 3, "RGB");
+
+#undef CHECK_PASS
+}
diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
index 2917bfd1236..7d4860ea1b5 100644
--- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
+++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
@@ -48,9 +48,10 @@ static struct {
/* Theses are just references, not actually allocated */
struct GPUTexture *depth_src;
struct GPUTexture *color_src;
-} e_data = {NULL}; /* Engine data */
+} e_data = {{NULL}}; /* Engine data */
extern char datatoc_ambient_occlusion_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
@@ -63,6 +64,7 @@ static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options)
{
if (e_data.ssr_sh[options] == NULL) {
char *ssr_shader_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
@@ -122,14 +124,15 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
const bool use_refraction = BKE_collection_engine_property_value_get_bool(props, "ssr_refraction");
if (use_refraction) {
- DRWFboTexture tex = {&txl->refract_color, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
+ /* TODO: Opti: Could be shared. */
+ DRW_texture_ensure_fullscreen_2D(&txl->refract_color, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER | DRW_TEX_MIPMAP);
- DRW_framebuffer_init(&fbl->refract_fb, &draw_engine_eevee_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex, 1);
+ GPU_framebuffer_ensure_config(&fbl->refract_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->refract_color)
+ });
}
- bool prev_trace_full = effects->reflection_trace_full;
effects->reflection_trace_full = !BKE_collection_engine_property_value_get_bool(props, "ssr_halfres");
common_data->ssr_thickness = BKE_collection_engine_property_value_get_float(props, "ssr_thickness");
common_data->ssr_border_fac = BKE_collection_engine_property_value_get_float(props, "ssr_border_fade");
@@ -142,47 +145,39 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
common_data->ssr_firefly_fac = FLT_MAX;
}
- if (prev_trace_full != effects->reflection_trace_full) {
- DRW_TEXTURE_FREE_SAFE(txl->ssr_hit_output);
- }
-
const int divisor = (effects->reflection_trace_full) ? 1 : 2;
int tracing_res[2] = {(int)viewport_size[0] / divisor, (int)viewport_size[1] / divisor};
+ int size_fs[2] = {(int)viewport_size[0], (int)viewport_size[1]};
const bool high_qual_input = true; /* TODO dither low quality input */
+ const DRWTextureFormat format = (high_qual_input) ? DRW_TEX_RGBA_16 : DRW_TEX_RGBA_8;
/* MRT for the shading pass in order to output needed data for the SSR pass. */
- /* TODO create one texture layer per lobe */
- if (txl->ssr_specrough_input == NULL) {
- DRWTextureFormat specrough_format = (high_qual_input) ? DRW_TEX_RGBA_16 : DRW_TEX_RGBA_8;
- txl->ssr_specrough_input = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1],
- specrough_format, 0, NULL);
- }
+ effects->ssr_specrough_input = DRW_texture_pool_query_2D(size_fs[0], size_fs[1], format,
+ &draw_engine_eevee_type);
- /* Reattach textures to the right buffer (because we are alternating between buffers) */
- /* TODO multiple FBO per texture!!!! */
- DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0);
+ GPU_framebuffer_texture_attach(fbl->main_fb, effects->ssr_specrough_input, 2, 0);
/* Raytracing output */
- /* (AMD or Intel) For some reason DRW_TEX_TEMP with DRW_TEX_RG_16I
- * creates problems when toggling ssr_halfres. Texture is not read correctly (black output).
- * So using a persistent buffer instead. */
- DRWFboTexture tex_output[2] = {{&txl->ssr_hit_output, DRW_TEX_RG_16I, 0},
- {&stl->g_data->ssr_pdf_output, DRW_TEX_R_16, DRW_TEX_TEMP}};
+ effects->ssr_hit_output = DRW_texture_pool_query_2D(tracing_res[0], tracing_res[1], DRW_TEX_RG_16I,
+ &draw_engine_eevee_type);
+ effects->ssr_pdf_output = DRW_texture_pool_query_2D(tracing_res[0], tracing_res[1], DRW_TEX_R_16,
+ &draw_engine_eevee_type);
- DRW_framebuffer_init(&fbl->screen_tracing_fb, &draw_engine_eevee_type,
- tracing_res[0], tracing_res[1],
- tex_output, 2);
+ GPU_framebuffer_ensure_config(&fbl->screen_tracing_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->ssr_hit_output),
+ GPU_ATTACHMENT_TEXTURE(effects->ssr_pdf_output)
+ });
/* Enable double buffering to be able to read previous frame color */
return EFFECT_SSR | EFFECT_NORMAL_BUFFER | EFFECT_DOUBLE_BUFFER | ((use_refraction) ? EFFECT_REFRACT : 0);
}
/* Cleanup to release memory */
- DRW_TEXTURE_FREE_SAFE(txl->ssr_specrough_input);
- DRW_TEXTURE_FREE_SAFE(txl->ssr_hit_output);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->screen_tracing_fb);
- stl->g_data->ssr_pdf_output = NULL;
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->screen_tracing_fb);
+ effects->ssr_specrough_input = NULL;
+ effects->ssr_hit_output = NULL;
+ effects->ssr_pdf_output = NULL;
return 0;
}
@@ -218,11 +213,11 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
*/
psl->ssr_raytrace = DRW_pass_create("SSR Raytrace", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(trace_shader, psl->ssr_raytrace);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
- DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
- DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input);
- DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
- DRW_shgroup_uniform_buffer(grp, "planarDepth", &vedata->txl->planar_depth);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input);
+ DRW_shgroup_uniform_texture_ref(grp, "specroughBuffer", &effects->ssr_specrough_input);
+ DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
+ DRW_shgroup_uniform_texture_ref(grp, "planarDepth", &vedata->txl->planar_depth);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
@@ -233,22 +228,22 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
psl->ssr_resolve = DRW_pass_create("SSR Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
grp = DRW_shgroup_create(resolve_shader, psl->ssr_resolve);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
- DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
- DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input);
- DRW_shgroup_uniform_buffer(grp, "probeCubes", &sldata->probe_pool);
- DRW_shgroup_uniform_buffer(grp, "probePlanars", &vedata->txl->planar_pool);
- DRW_shgroup_uniform_buffer(grp, "planarDepth", &vedata->txl->planar_depth);
- DRW_shgroup_uniform_buffer(grp, "hitBuffer", &vedata->txl->ssr_hit_output);
- DRW_shgroup_uniform_buffer(grp, "pdfBuffer", &stl->g_data->ssr_pdf_output);
- DRW_shgroup_uniform_buffer(grp, "prevColorBuffer", &txl->color_double_buffer);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input);
+ DRW_shgroup_uniform_texture_ref(grp, "specroughBuffer", &effects->ssr_specrough_input);
+ DRW_shgroup_uniform_texture_ref(grp, "probeCubes", &sldata->probe_pool);
+ DRW_shgroup_uniform_texture_ref(grp, "probePlanars", &vedata->txl->planar_pool);
+ DRW_shgroup_uniform_texture_ref(grp, "planarDepth", &vedata->txl->planar_depth);
+ DRW_shgroup_uniform_texture_ref(grp, "hitBuffer", &effects->ssr_hit_output);
+ DRW_shgroup_uniform_texture_ref(grp, "pdfBuffer", &effects->ssr_pdf_output);
+ DRW_shgroup_uniform_texture_ref(grp, "prevColorBuffer", &txl->color_double_buffer);
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_int(grp, "neighborOffset", &effects->ssr_neighbor_ofs, 1);
if ((effects->enabled_effects & EFFECT_GTAO) != 0) {
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &vedata->txl->gtao_horizons);
+ DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons);
}
DRW_shgroup_call_add(grp, quad, NULL);
@@ -263,12 +258,11 @@ void EEVEE_refraction_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
EEVEE_EffectsInfo *effects = stl->effects;
if ((effects->enabled_effects & EFFECT_REFRACT) != 0) {
- DRW_framebuffer_texture_attach(fbl->refract_fb, txl->refract_color, 0, 0);
- DRW_framebuffer_blit(fbl->main, fbl->refract_fb, false, false);
- EEVEE_downsample_buffer(vedata, fbl->downsample_fb, txl->refract_color, 9);
+ GPU_framebuffer_blit(fbl->main_fb, 0, fbl->refract_fb, 0, GPU_COLOR_BIT);
+ EEVEE_downsample_buffer(vedata, txl->refract_color, 9);
/* Restore */
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_bind(fbl->main_fb);
}
}
@@ -285,15 +279,12 @@ void EEVEE_reflection_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
e_data.depth_src = dtxl->depth;
DRW_stats_group_start("SSR");
- DRW_framebuffer_texture_attach(fbl->screen_tracing_fb, stl->g_data->ssr_pdf_output, 1, 0);
- DRW_framebuffer_bind(fbl->screen_tracing_fb);
/* Raytrace. */
+ GPU_framebuffer_bind(fbl->screen_tracing_fb);
DRW_draw_pass(psl->ssr_raytrace);
- DRW_framebuffer_texture_detach(stl->g_data->ssr_pdf_output);
-
- EEVEE_downsample_buffer(vedata, fbl->downsample_fb, txl->color_double_buffer, 9);
+ EEVEE_downsample_buffer(vedata, txl->color_double_buffer, 9);
/* Resolve at fullres */
int sample = (DRW_state_is_image_render()) ? effects->taa_render_sample : effects->taa_current_sample;
@@ -318,18 +309,11 @@ void EEVEE_reflection_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
effects->ssr_halfres_ofs[1] = 1;
break;
}
- DRW_framebuffer_texture_detach(dtxl->depth);
- DRW_framebuffer_texture_detach(txl->ssr_normal_input);
- DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_bind(fbl->main_color_fb);
DRW_draw_pass(psl->ssr_resolve);
/* Restore */
- DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 1, 0);
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0);
- DRW_framebuffer_bind(fbl->main);
-
+ GPU_framebuffer_bind(fbl->main_fb);
DRW_stats_group_end();
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index 17da4a18b78..ebaf559d22b 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -33,15 +33,17 @@
#include "GPU_texture.h"
static struct {
- struct GPUShader *sss_sh[3];
-} e_data = {NULL}; /* Engine data */
+ struct GPUShader *sss_sh[4];
+} e_data = {{NULL}}; /* Engine data */
+extern char datatoc_common_view_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_effect_subsurface_frag_glsl[];
static void eevee_create_shader_subsurface(void)
{
char *frag_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_effect_subsurface_frag_glsl);
@@ -49,6 +51,9 @@ static void eevee_create_shader_subsurface(void)
e_data.sss_sh[1] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n");
e_data.sss_sh[2] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n"
"#define USE_SEP_ALBEDO\n");
+ e_data.sss_sh[3] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n"
+ "#define USE_SEP_ALBEDO\n"
+ "#define RESULT_ACCUM\n");
MEM_freeN(frag_str);
}
@@ -61,6 +66,7 @@ int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
const float *viewport_size = DRW_viewport_size_get();
+ const int fs_size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
@@ -71,6 +77,11 @@ int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
effects->sss_separate_albedo = BKE_collection_engine_property_value_get_bool(props, "sss_separate_albedo");
common_data->sss_jitter_threshold = BKE_collection_engine_property_value_get_float(props, "sss_jitter_threshold");
+ /* Force separate albedo for final render */
+ if (DRW_state_is_image_render()) {
+ effects->sss_separate_albedo = true;
+ }
+
/* Shaders */
if (!e_data.sss_sh[0]) {
eevee_create_shader_subsurface();
@@ -80,35 +91,94 @@ int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
* as the depth buffer we are sampling from. This could be avoided if the stencil is
* a separate texture but that needs OpenGL 4.4 or ARB_texture_stencil8.
* OR OpenGL 4.3 / ARB_ES3_compatibility if using a renderbuffer instead */
- DRWFboTexture texs[2] = {{&txl->sss_stencil, DRW_TEX_DEPTH_24_STENCIL_8, 0},
- {&txl->sss_blur, DRW_TEX_RGBA_16, DRW_TEX_FILTER}};
-
- DRW_framebuffer_init(&fbl->sss_blur_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1],
- texs, 2);
+ effects->sss_stencil = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], DRW_TEX_DEPTH_24_STENCIL_8,
+ &draw_engine_eevee_type);
+ effects->sss_blur = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], DRW_TEX_RGBA_16,
+ &draw_engine_eevee_type);
+ effects->sss_data = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], DRW_TEX_RGBA_16,
+ &draw_engine_eevee_type);
+
+ GPU_framebuffer_ensure_config(&fbl->sss_blur_fb, {
+ GPU_ATTACHMENT_TEXTURE(effects->sss_stencil),
+ GPU_ATTACHMENT_TEXTURE(effects->sss_blur)
+ });
+
+ GPU_framebuffer_ensure_config(&fbl->sss_resolve_fb, {
+ GPU_ATTACHMENT_TEXTURE(effects->sss_stencil),
+ GPU_ATTACHMENT_TEXTURE(txl->color)
+ });
+
+ GPU_framebuffer_ensure_config(&fbl->sss_clear_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->sss_data)
+ });
- DRWFboTexture tex_data = {&txl->sss_data, DRW_TEX_RGBA_16, DRW_TEX_FILTER};
- DRW_framebuffer_init(&fbl->sss_clear_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1],
- &tex_data, 1);
-
- if (effects->sss_separate_albedo && (txl->sss_albedo == NULL)) {
- txl->sss_albedo = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1],
- DRW_TEX_RGB_11_11_10, 0, NULL);
+ if (effects->sss_separate_albedo) {
+ effects->sss_albedo = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], DRW_TEX_RGB_11_11_10,
+ &draw_engine_eevee_type);
+ }
+ else {
+ effects->sss_albedo = NULL;
}
-
return EFFECT_SSS;
}
/* Cleanup to release memory */
- DRW_TEXTURE_FREE_SAFE(txl->sss_albedo);
- DRW_TEXTURE_FREE_SAFE(txl->sss_data);
- DRW_TEXTURE_FREE_SAFE(txl->sss_blur);
- DRW_TEXTURE_FREE_SAFE(txl->sss_stencil);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->sss_blur_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->sss_clear_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_blur_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_resolve_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_clear_fb);
+ effects->sss_stencil = NULL;
+ effects->sss_blur = NULL;
+ effects->sss_data = NULL;
return 0;
}
+static void set_shgrp_stencil(void *UNUSED(userData), DRWShadingGroup *shgrp)
+{
+ DRW_shgroup_stencil_mask(shgrp, 255);
+}
+
+void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+
+ if (BKE_collection_engine_property_value_get_bool(props, "sss_enable")) {
+ DRW_texture_ensure_fullscreen_2D(&txl->sss_dir_accum, DRW_TEX_RGBA_16, 0);
+ DRW_texture_ensure_fullscreen_2D(&txl->sss_col_accum, DRW_TEX_RGBA_16, 0);
+
+ GPU_framebuffer_ensure_config(&fbl->sss_accum_fb, {
+ GPU_ATTACHMENT_TEXTURE(effects->sss_stencil),
+ GPU_ATTACHMENT_TEXTURE(txl->sss_dir_accum),
+ GPU_ATTACHMENT_TEXTURE(txl->sss_col_accum)
+ });
+
+ /* Clear texture. */
+ float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ GPU_framebuffer_bind(fbl->sss_accum_fb);
+ GPU_framebuffer_clear_color(fbl->sss_accum_fb, clear);
+
+ /* Make the opaque refraction pass mask the sss. */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
+ DRW_STATE_WIRE | DRW_STATE_WRITE_STENCIL;
+ DRW_pass_state_set(vedata->psl->refract_pass, state);
+ DRW_pass_foreach_shgroup(vedata->psl->refract_pass, &set_shgrp_stencil, NULL);
+ }
+ else {
+ /* Cleanup to release memory */
+ DRW_TEXTURE_FREE_SAFE(txl->sss_dir_accum);
+ DRW_TEXTURE_FREE_SAFE(txl->sss_col_accum);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb);
+ }
+}
+
void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
@@ -121,7 +191,9 @@ void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
*/
psl->sss_blur_ps = DRW_pass_create("Blur Horiz", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL);
- psl->sss_resolve_ps = DRW_pass_create("Blur Vert", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE | DRW_STATE_STENCIL_EQUAL);
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE | DRW_STATE_STENCIL_EQUAL;
+ psl->sss_resolve_ps = DRW_pass_create("Blur Vert", state);
+ psl->sss_accum_ps = DRW_pass_create("Resolve Accum", state);
}
}
@@ -129,7 +201,6 @@ void EEVEE_subsurface_add_pass(
EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile)
{
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- EEVEE_TextureList *txl = vedata->txl;
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
@@ -137,8 +208,8 @@ void EEVEE_subsurface_add_pass(
DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_data);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_texture_ref(grp, "sssData", &effects->sss_data);
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_stencil_mask(grp, sss_id);
@@ -147,22 +218,33 @@ void EEVEE_subsurface_add_pass(
struct GPUShader *sh = (effects->sss_separate_albedo) ? e_data.sss_sh[2] : e_data.sss_sh[1];
grp = DRW_shgroup_create(sh, psl->sss_resolve_ps);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_blur);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_texture_ref(grp, "sssData", &effects->sss_blur);
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_stencil_mask(grp, sss_id);
DRW_shgroup_call_add(grp, quad, NULL);
if (effects->sss_separate_albedo) {
- DRW_shgroup_uniform_buffer(grp, "sssAlbedo", &txl->sss_albedo);
+ DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
+ }
+
+ if (DRW_state_is_image_render()) {
+ grp = DRW_shgroup_create(e_data.sss_sh[3], psl->sss_accum_ps);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_texture_ref(grp, "sssData", &effects->sss_blur);
+ DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_stencil_mask(grp, sss_id);
+ DRW_shgroup_call_add(grp, quad, NULL);
}
}
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
- EEVEE_TextureList *txl = vedata->txl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
@@ -170,98 +252,88 @@ void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
if ((effects->enabled_effects & EFFECT_SSS) != 0) {
float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
/* Clear sss_data texture only... can this be done in a more clever way? */
- DRW_framebuffer_bind(fbl->sss_clear_fb);
- DRW_framebuffer_clear(true, false, false, clear, 0.0f);
-
-
- DRW_framebuffer_texture_detach(txl->sss_data);
- if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
- DRW_framebuffer_texture_detach(txl->ssr_normal_input);
- }
- if ((effects->enabled_effects & EFFECT_SSR) != 0) {
- DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
- }
-
- /* Start at slot 1 because slot 0 is txl->color */
- int tex_slot = 1;
- DRW_framebuffer_texture_attach(fbl->main, txl->sss_data, tex_slot++, 0);
- if (effects->sss_separate_albedo) {
- DRW_framebuffer_texture_attach(fbl->main, txl->sss_albedo, tex_slot++, 0);
- }
- if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, tex_slot++, 0);
- }
- if ((effects->enabled_effects & EFFECT_SSR) != 0) {
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, tex_slot++, 0);
- }
- DRW_framebuffer_bind(fbl->main);
-
+ GPU_framebuffer_bind(fbl->sss_clear_fb);
+ GPU_framebuffer_clear_color(fbl->sss_clear_fb, clear);
+
+ GPU_framebuffer_ensure_config(&fbl->main_fb, {
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_TEXTURE(effects->sss_data),
+ GPU_ATTACHMENT_TEXTURE(effects->sss_albedo)
+ });
+
+ GPU_framebuffer_bind(fbl->main_fb);
DRW_draw_pass(psl->sss_pass);
/* Restore */
- DRW_framebuffer_texture_detach(txl->sss_data);
- if (effects->sss_separate_albedo) {
- DRW_framebuffer_texture_detach(txl->sss_albedo);
- }
- if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
- DRW_framebuffer_texture_detach(txl->ssr_normal_input);
- }
- if ((effects->enabled_effects & EFFECT_SSR) != 0) {
- DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
- }
-
- DRW_framebuffer_texture_attach(fbl->sss_clear_fb, txl->sss_data, 0, 0);
- if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 1, 0);
- }
- if ((effects->enabled_effects & EFFECT_SSR) != 0) {
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0);
- }
+ GPU_framebuffer_ensure_config(&fbl->main_fb, {
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_NONE
+ });
}
}
void EEVEE_subsurface_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
- EEVEE_FramebufferList *fbl = vedata->fbl;
- EEVEE_TextureList *txl = vedata->txl;
EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_EffectsInfo *effects = stl->effects;
if ((effects->enabled_effects & EFFECT_SSS) != 0) {
float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
DRW_stats_group_start("SSS");
/* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */
- DRW_framebuffer_blit(fbl->main, fbl->sss_blur_fb, false, true);
-
- DRW_framebuffer_texture_detach(dtxl->depth);
+ GPU_framebuffer_blit(fbl->main_fb, 0, fbl->sss_blur_fb, 0, GPU_STENCIL_BIT);
- /* First horizontal pass */
- DRW_framebuffer_bind(fbl->sss_blur_fb);
- DRW_framebuffer_clear(true, false, false, clear, 0.0f);
+ /* 1. horizontal pass */
+ GPU_framebuffer_bind(fbl->sss_blur_fb);
+ GPU_framebuffer_clear_color(fbl->sss_blur_fb, clear);
DRW_draw_pass(psl->sss_blur_ps);
- /* First vertical pass + Resolve */
- DRW_framebuffer_texture_detach(txl->sss_stencil);
- DRW_framebuffer_texture_attach(fbl->main, txl->sss_stencil, 0, 0);
- DRW_framebuffer_bind(fbl->main);
+ /* 2. vertical pass + Resolve */
+ GPU_framebuffer_texture_attach(fbl->sss_resolve_fb, txl->color, 0, 0);
+ GPU_framebuffer_bind(fbl->sss_resolve_fb);
DRW_draw_pass(psl->sss_resolve_ps);
- /* Restore */
- DRW_framebuffer_texture_detach(txl->sss_stencil);
- DRW_framebuffer_texture_attach(fbl->sss_blur_fb, txl->sss_stencil, 0, 0);
- DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
-
+ GPU_framebuffer_bind(fbl->main_fb);
DRW_stats_group_end();
}
}
+void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ if (((effects->enabled_effects & EFFECT_SSS) != 0) && (fbl->sss_accum_fb != NULL)) {
+ /* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */
+ GPU_framebuffer_blit(fbl->main_fb, 0, fbl->sss_blur_fb, 0, GPU_STENCIL_BIT);
+
+ /* Only do vertical pass + Resolve */
+ GPU_framebuffer_bind(fbl->sss_accum_fb);
+ DRW_draw_pass(psl->sss_accum_ps);
+
+ /* Restore */
+ GPU_framebuffer_bind(fbl->main_fb);
+ }
+}
+
void EEVEE_subsurface_free(void)
{
DRW_SHADER_FREE_SAFE(e_data.sss_sh[0]);
DRW_SHADER_FREE_SAFE(e_data.sss_sh[1]);
DRW_SHADER_FREE_SAFE(e_data.sss_sh[2]);
+ DRW_SHADER_FREE_SAFE(e_data.sss_sh[3]);
}
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index 3ed2a20e68c..acc1bff6331 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -32,9 +32,14 @@
#include "eevee_private.h"
#include "GPU_texture.h"
+#define FILTER_CDF_TABLE_SIZE 512
+
static struct {
/* Temporal Anti Aliasing */
struct GPUShader *taa_resolve_sh;
+
+ /* Pixel filter table: Only blackman-harris for now. */
+ float inverted_cdf[FILTER_CDF_TABLE_SIZE];
} e_data = {NULL}; /* Engine data */
extern char datatoc_effect_temporal_aa_glsl[];
@@ -44,6 +49,113 @@ static void eevee_create_shader_temporal_sampling(void)
e_data.taa_resolve_sh = DRW_shader_create_fullscreen(datatoc_effect_temporal_aa_glsl, NULL);
}
+static float UNUSED_FUNCTION(filter_box)(float UNUSED(x))
+{
+ return 1.0f;
+}
+
+static float filter_blackman_harris(float x)
+{
+ /* Hardcoded 1px footprint [-0.5..0.5]. We resize later. */
+ const float width = 1.0f;
+ x = 2.0f * M_PI * (x / width + 0.5f);
+ return 0.35875f - 0.48829f * cosf(x) + 0.14128f * cosf(2.0f * x) - 0.01168f * cosf(3.0f * x);
+}
+
+/* Compute cumulative distribution function of a discrete function. */
+static void compute_cdf(float (*func)(float x), float cdf[FILTER_CDF_TABLE_SIZE])
+{
+ cdf[0] = 0.0f;
+ /* Actual CDF evaluation. */
+ for (int u = 0; u < FILTER_CDF_TABLE_SIZE - 1; ++u) {
+ float x = (float)(u + 1) / (float)(FILTER_CDF_TABLE_SIZE - 1);
+ cdf[u + 1] = cdf[u] + func(x - 0.5f); /* [-0.5..0.5]. We resize later. */
+ }
+ /* Normalize the CDF. */
+ for (int u = 0; u < FILTER_CDF_TABLE_SIZE - 1; u++) {
+ cdf[u] /= cdf[FILTER_CDF_TABLE_SIZE - 1];
+ }
+ /* Just to make sure. */
+ cdf[FILTER_CDF_TABLE_SIZE - 1] = 1.0f;
+}
+
+static void invert_cdf(const float cdf[FILTER_CDF_TABLE_SIZE], float invert_cdf[FILTER_CDF_TABLE_SIZE])
+{
+ for (int u = 0; u < FILTER_CDF_TABLE_SIZE; u++) {
+ float x = (float)u / (float)(FILTER_CDF_TABLE_SIZE - 1);
+ for (int i = 0; i < FILTER_CDF_TABLE_SIZE; ++i) {
+ if (cdf[i] >= x) {
+ if (i == FILTER_CDF_TABLE_SIZE - 1) {
+ invert_cdf[u] = 1.0f;
+ }
+ else {
+ float t = (x - cdf[i]) / (cdf[i + 1] - cdf[i]);
+ invert_cdf[u] = ((float)i + t) / (float)(FILTER_CDF_TABLE_SIZE - 1);
+ }
+ break;
+ }
+ }
+ }
+}
+
+/* Evaluate a discrete function table with linear interpolation. */
+static float eval_table(float *table, float x)
+{
+ CLAMP(x, 0.0f, 1.0f);
+ x = x * (FILTER_CDF_TABLE_SIZE - 1);
+
+ int index = min_ii((int)(x), FILTER_CDF_TABLE_SIZE - 1);
+ int nindex = min_ii(index + 1, FILTER_CDF_TABLE_SIZE - 1);
+ float t = x - index;
+
+ return (1.0f - t) * table[index] + t * table[nindex];
+}
+
+static void eevee_create_cdf_table_temporal_sampling(void)
+{
+ float *cdf_table = MEM_mallocN(sizeof(float) * FILTER_CDF_TABLE_SIZE, "Eevee Filter CDF table");
+
+ float filter_width = 2.0f; /* Use a 2 pixel footprint by default. */
+
+ {
+ /* Use blackman-harris filter. */
+ filter_width *= 2.0f;
+ compute_cdf(filter_blackman_harris, cdf_table);
+ }
+
+ invert_cdf(cdf_table, e_data.inverted_cdf);
+
+ /* Scale and offset table. */
+ for (int i = 0; i < FILTER_CDF_TABLE_SIZE; ++i) {
+ e_data.inverted_cdf[i] = (e_data.inverted_cdf[i] - 0.5f) * filter_width;
+ }
+
+ MEM_freeN(cdf_table);
+}
+
+void EEVEE_temporal_sampling_matrices_calc(
+ EEVEE_EffectsInfo *effects, float viewmat[4][4], float persmat[4][4], const double ht_point[2])
+{
+ const float *viewport_size = DRW_viewport_size_get();
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ RenderData *rd = &scene->r;
+
+ float filter_size = rd->gauss; /* Sigh.. Stupid legacy naming. */
+
+ float ofs_x = eval_table(e_data.inverted_cdf, (float)(ht_point[0])) * filter_size;
+ float ofs_y = eval_table(e_data.inverted_cdf, (float)(ht_point[1])) * filter_size;
+
+ window_translate_m4(
+ effects->overide_winmat, persmat,
+ ofs_x / viewport_size[0],
+ ofs_y / viewport_size[1]);
+
+ mul_m4_m4m4(effects->overide_persmat, effects->overide_winmat, viewmat);
+ invert_m4_m4(effects->overide_persinv, effects->overide_persmat);
+ invert_m4_m4(effects->overide_wininv, effects->overide_winmat);
+}
+
int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = vedata->stl;
@@ -67,11 +179,11 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
(effects->enabled_effects & EFFECT_MOTION_BLUR) == 0) ||
DRW_state_is_image_render())
{
- const float *viewport_size = DRW_viewport_size_get();
float persmat[4][4], viewmat[4][4];
if (!e_data.taa_resolve_sh) {
eevee_create_shader_temporal_sampling();
+ eevee_create_cdf_table_temporal_sampling();
}
/* Until we support reprojection, we need to make sure
@@ -110,14 +222,7 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
BLI_halton_2D(ht_primes, ht_offset, effects->taa_current_sample - 1, ht_point);
- window_translate_m4(
- effects->overide_winmat, persmat,
- ((float)(ht_point[0]) * 2.0f - 1.0f) / viewport_size[0],
- ((float)(ht_point[1]) * 2.0f - 1.0f) / viewport_size[1]);
-
- mul_m4_m4m4(effects->overide_persmat, effects->overide_winmat, viewmat);
- invert_m4_m4(effects->overide_persinv, effects->overide_persmat);
- invert_m4_m4(effects->overide_wininv, effects->overide_winmat);
+ EEVEE_temporal_sampling_matrices_calc(effects, viewmat, persmat, ht_point);
DRW_viewport_matrix_override_set(effects->overide_persmat, DRW_MAT_PERS);
DRW_viewport_matrix_override_set(effects->overide_persinv, DRW_MAT_PERSINV);
@@ -133,18 +238,20 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
effects->taa_current_sample = 1;
}
- DRWFboTexture tex_double_buffer = {&txl->depth_double_buffer, DRW_TEX_DEPTH_24_STENCIL_8, 0};
+ DRW_texture_ensure_fullscreen_2D(&txl->depth_double_buffer, DRW_TEX_DEPTH_24_STENCIL_8, 0);
- DRW_framebuffer_init(&fbl->depth_double_buffer_fb, &draw_engine_eevee_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex_double_buffer, 1);
+ GPU_framebuffer_ensure_config(&fbl->double_buffer_depth_fb, {
+ GPU_ATTACHMENT_TEXTURE(txl->depth_double_buffer)
+ });
return EFFECT_TAA | EFFECT_DOUBLE_BUFFER | EFFECT_POST_BUFFER;
}
+ effects->taa_current_sample = 1;
+
/* Cleanup to release memory */
DRW_TEXTURE_FREE_SAFE(txl->depth_double_buffer);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->depth_double_buffer_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->double_buffer_depth_fb);
return 0;
}
@@ -160,8 +267,8 @@ void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEV
psl->taa_resolve = DRW_pass_create("Temporal AA Resolve", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.taa_resolve_sh, psl->taa_resolve);
- DRW_shgroup_uniform_buffer(grp, "historyBuffer", &txl->color_double_buffer);
- DRW_shgroup_uniform_buffer(grp, "colorBuffer", &txl->color);
+ DRW_shgroup_uniform_texture_ref(grp, "historyBuffer", &txl->color_double_buffer);
+ DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &txl->color);
DRW_shgroup_uniform_float(grp, "alpha", &effects->taa_alpha, 1);
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
@@ -185,24 +292,29 @@ void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata)
effects->taa_alpha = 1.0f / (float)(effects->taa_current_sample);
}
- DRW_framebuffer_bind(fbl->effect_fb);
+ GPU_framebuffer_bind(fbl->effect_color_fb);
DRW_draw_pass(psl->taa_resolve);
/* Restore the depth from sample 1. */
- DRW_framebuffer_blit(fbl->depth_double_buffer_fb, fbl->main, true, false);
+ if (!DRW_state_is_image_render()) {
+ GPU_framebuffer_blit(fbl->double_buffer_depth_fb, 0, fbl->main_fb, 0, GPU_DEPTH_BIT);
+ }
/* Special Swap */
- SWAP(struct GPUFrameBuffer *, fbl->effect_fb, fbl->double_buffer);
+ SWAP(struct GPUFrameBuffer *, fbl->effect_fb, fbl->double_buffer_fb);
+ SWAP(struct GPUFrameBuffer *, fbl->effect_color_fb, fbl->double_buffer_color_fb);
SWAP(GPUTexture *, txl->color_post, txl->color_double_buffer);
effects->swap_double_buffer = false;
effects->source_buffer = txl->color_double_buffer;
- effects->target_buffer = fbl->main;
+ effects->target_buffer = fbl->main_color_fb;
}
else {
/* Save the depth buffer for the next frame.
* This saves us from doing anything special
* in the other mode engines. */
- DRW_framebuffer_blit(fbl->main, fbl->depth_double_buffer_fb, true, false);
+ if (!DRW_state_is_image_render()) {
+ GPU_framebuffer_blit(fbl->main_fb, 0, fbl->double_buffer_depth_fb, 0, GPU_DEPTH_BIT);
+ }
}
/* Make each loop count when doing a render. */
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index a960682e8c9..408015addd4 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -30,7 +30,7 @@
#include "BLI_rand.h"
#include "BLI_string_utils.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_smoke_types.h"
#include "DNA_world_types.h"
@@ -65,6 +65,7 @@ static struct {
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_direct_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
extern char datatoc_irradiance_lib_glsl[];
extern char datatoc_lamps_lib_glsl[];
@@ -75,16 +76,18 @@ extern char datatoc_volumetric_resolve_frag_glsl[];
extern char datatoc_volumetric_scatter_frag_glsl[];
extern char datatoc_volumetric_integration_frag_glsl[];
extern char datatoc_volumetric_lib_glsl[];
-extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
+extern char datatoc_common_fullscreen_vert_glsl[];
static void eevee_create_shader_volumes(void)
{
e_data.volumetric_common_lib = BLI_string_joinN(
+ datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_volumetric_lib_glsl);
e_data.volumetric_common_lamps_lib = BLI_string_joinN(
+ datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_direct_lib_glsl,
@@ -123,11 +126,26 @@ static void eevee_create_shader_volumes(void)
datatoc_volumetric_integration_frag_glsl,
e_data.volumetric_common_lib, NULL);
e_data.volumetric_resolve_sh = DRW_shader_create_with_lib(
- datatoc_gpu_shader_fullscreen_vert_glsl, NULL,
+ datatoc_common_fullscreen_vert_glsl, NULL,
datatoc_volumetric_resolve_frag_glsl,
e_data.volumetric_common_lib, NULL);
}
+void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, unsigned int current_sample)
+{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
+
+ double ht_point[3];
+ double ht_offset[3] = {0.0, 0.0};
+ unsigned int ht_primes[3] = {3, 7, 2};
+
+ BLI_halton_3D(ht_primes, ht_offset, current_sample, ht_point);
+
+ common_data->vol_jitter[0] = (float)ht_point[0];
+ common_data->vol_jitter[1] = (float)ht_point[1];
+ common_data->vol_jitter[2] = (float)ht_point[2];
+}
+
int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = vedata->stl;
@@ -177,9 +195,9 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance);
DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance_history);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
common_data->vol_tex_size[0] = tex_size[0];
common_data->vol_tex_size[1] = tex_size[1];
common_data->vol_tex_size[2] = tex_size[2];
@@ -223,8 +241,6 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
/* Temporal Super sampling jitter */
- double ht_point[3];
- double ht_offset[3] = {0.0, 0.0};
unsigned int ht_primes[3] = {3, 7, 2};
unsigned int current_sample = 0;
@@ -248,35 +264,27 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_viewport_request_redraw();
}
}
- BLI_halton_3D(ht_primes, ht_offset, current_sample, ht_point);
- common_data->vol_jitter[0] = (float)ht_point[0];
- common_data->vol_jitter[1] = (float)ht_point[1];
- common_data->vol_jitter[2] = (float)ht_point[2];
+ EEVEE_volumes_set_jitter(sldata, current_sample);
/* Framebuffer setup */
- DRWFboTexture tex_vol[4] = {{&txl->volume_prop_scattering, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
- {&txl->volume_prop_extinction, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
- {&txl->volume_prop_emission, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
- {&txl->volume_prop_phase, DRW_TEX_RG_16, DRW_TEX_FILTER}};
-
- DRW_framebuffer_init(&fbl->volumetric_fb, &draw_engine_eevee_type,
- (int)tex_size[0], (int)tex_size[1],
- tex_vol, 4);
-
- DRWFboTexture tex_vol_scat[2] = {{&txl->volume_scatter, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
- {&txl->volume_transmittance, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}};
-
- DRW_framebuffer_init(&fbl->volumetric_scat_fb, &draw_engine_eevee_type,
- (int)tex_size[0], (int)tex_size[1],
- tex_vol_scat, 2);
-
- DRWFboTexture tex_vol_integ[2] = {{&txl->volume_scatter_history, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
- {&txl->volume_transmittance_history, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}};
-
- DRW_framebuffer_init(&fbl->volumetric_integ_fb, &draw_engine_eevee_type,
- (int)tex_size[0], (int)tex_size[1],
- tex_vol_integ, 2);
+ GPU_framebuffer_ensure_config(&fbl->volumetric_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->volume_prop_scattering),
+ GPU_ATTACHMENT_TEXTURE(txl->volume_prop_extinction),
+ GPU_ATTACHMENT_TEXTURE(txl->volume_prop_emission),
+ GPU_ATTACHMENT_TEXTURE(txl->volume_prop_phase)
+ });
+ GPU_framebuffer_ensure_config(&fbl->volumetric_scat_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->volume_scatter),
+ GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance)
+ });
+ GPU_framebuffer_ensure_config(&fbl->volumetric_integ_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->volume_scatter_history),
+ GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance_history)
+ });
float integration_start = BKE_collection_engine_property_value_get_float(props, "volumetric_start");
float integration_end = BKE_collection_engine_property_value_get_float(props, "volumetric_end");
@@ -304,7 +312,7 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
else {
const float clip_start = common_data->view_vecs[0][2];
- const float clip_end = common_data->view_vecs[1][2];
+ const float clip_end = clip_start + common_data->view_vecs[1][2];
integration_start = min_ff(integration_end, clip_start);
integration_end = max_ff(-integration_end, clip_end);
@@ -332,9 +340,9 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance);
DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance_history);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
return 0;
}
@@ -350,7 +358,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- DRWShadingGroup *grp;
+ DRWShadingGroup *grp = NULL;
/* Quick breakdown of the Volumetric rendering:
*
@@ -394,7 +402,8 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
}
}
- else {
+
+ if (grp == NULL) {
/* If no world or volume material is present just clear the buffer with this drawcall */
grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_clear_sh,
psl->volumetric_world_ps,
@@ -412,14 +421,14 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
psl->volumetric_scatter_ps = DRW_pass_create("Volumetric Scattering", DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_empty_tri_batch_create(scatter_sh, psl->volumetric_scatter_ps,
common_data->vol_tex_size[2]);
- DRW_shgroup_uniform_buffer(grp, "irradianceGrid", &sldata->irradiance_pool);
- DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_pool);
- DRW_shgroup_uniform_buffer(grp, "volumeScattering", &txl->volume_prop_scattering);
- DRW_shgroup_uniform_buffer(grp, "volumeExtinction", &txl->volume_prop_extinction);
- DRW_shgroup_uniform_buffer(grp, "volumeEmission", &txl->volume_prop_emission);
- DRW_shgroup_uniform_buffer(grp, "volumePhase", &txl->volume_prop_phase);
- DRW_shgroup_uniform_buffer(grp, "historyScattering", &txl->volume_scatter_history);
- DRW_shgroup_uniform_buffer(grp, "historyTransmittance", &txl->volume_transmittance_history);
+ DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &sldata->irradiance_pool);
+ DRW_shgroup_uniform_texture_ref(grp, "shadowTexture", &sldata->shadow_pool);
+ DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_prop_scattering);
+ DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_prop_extinction);
+ DRW_shgroup_uniform_texture_ref(grp, "volumeEmission", &txl->volume_prop_emission);
+ DRW_shgroup_uniform_texture_ref(grp, "volumePhase", &txl->volume_prop_phase);
+ DRW_shgroup_uniform_texture_ref(grp, "historyScattering", &txl->volume_scatter_history);
+ DRW_shgroup_uniform_texture_ref(grp, "historyTransmittance", &txl->volume_transmittance_history);
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
@@ -428,16 +437,16 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_integration_sh,
psl->volumetric_integration_ps,
common_data->vol_tex_size[2]);
- DRW_shgroup_uniform_buffer(grp, "volumeScattering", &txl->volume_scatter);
- DRW_shgroup_uniform_buffer(grp, "volumeExtinction", &txl->volume_transmittance);
+ DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_scatter);
+ DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_transmittance);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
psl->volumetric_resolve_ps = DRW_pass_create("Volumetric Resolve", DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(e_data.volumetric_resolve_sh, psl->volumetric_resolve_ps);
- DRW_shgroup_uniform_buffer(grp, "inScattering", &txl->volume_scatter);
- DRW_shgroup_uniform_buffer(grp, "inTransmittance", &txl->volume_transmittance);
- DRW_shgroup_uniform_buffer(grp, "inSceneColor", &e_data.color_src);
- DRW_shgroup_uniform_buffer(grp, "inSceneDepth", &e_data.depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "inScattering", &txl->volume_scatter);
+ DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmittance);
+ DRW_shgroup_uniform_texture_ref(grp, "inSceneColor", &e_data.color_src);
+ DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
@@ -458,17 +467,20 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
DRWShadingGroup *grp = DRW_shgroup_material_empty_tri_batch_create(mat, vedata->psl->volumetric_objects_ps, sldata->common_data.vol_tex_size[2]);
+ /* If shader failed to compile or is currently compiling. */
+ if (grp == NULL) {
+ return;
+ }
+
/* Making sure it's updated. */
invert_m4_m4(ob->imat, ob->obmat);
BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texcoloc, NULL, &texcosize);
- if (grp) {
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_mat4(grp, "volumeObjectMatrix", (float *)ob->imat);
- DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1);
- DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1);
- }
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_mat4(grp, "volumeObjectMatrix", (float *)ob->imat);
+ DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1);
+ DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1);
/* Smoke Simulation */
if (((ob->base_flag & BASE_FROMDUPLI) == 0) &&
@@ -491,11 +503,14 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
}
if (sds->tex != NULL) {
- DRW_shgroup_uniform_buffer(grp, "sampdensity", &sds->tex);
+ DRW_shgroup_uniform_texture_ref(grp, "sampdensity", &sds->tex);
}
if (sds->tex_flame != NULL) {
- DRW_shgroup_uniform_buffer(grp, "sampflame", &sds->tex_flame);
+ DRW_shgroup_uniform_texture_ref(grp, "sampflame", &sds->tex_flame);
}
+
+ /* Output is such that 0..1 maps to 0..1000K */
+ DRW_shgroup_uniform_vec2(grp, "unftemperature", &sds->flame_ignition, 1);
}
}
@@ -510,16 +525,16 @@ void EEVEE_volumes_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda
DRW_stats_group_start("Volumetrics");
/* Step 1: Participating Media Properties */
- DRW_framebuffer_bind(fbl->volumetric_fb);
+ GPU_framebuffer_bind(fbl->volumetric_fb);
DRW_draw_pass(psl->volumetric_world_ps);
DRW_draw_pass(psl->volumetric_objects_ps);
/* Step 2: Scatter Light */
- DRW_framebuffer_bind(fbl->volumetric_scat_fb);
+ GPU_framebuffer_bind(fbl->volumetric_scat_fb);
DRW_draw_pass(psl->volumetric_scatter_ps);
/* Step 3: Integration */
- DRW_framebuffer_bind(fbl->volumetric_integ_fb);
+ GPU_framebuffer_bind(fbl->volumetric_integ_fb);
DRW_draw_pass(psl->volumetric_integration_ps);
/* Swap volume history buffers */
@@ -528,7 +543,7 @@ void EEVEE_volumes_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda
SWAP(GPUTexture *, txl->volume_transmittance, txl->volume_transmittance_history);
/* Restore */
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_bind(fbl->main_fb);
DRW_stats_group_end();
}
@@ -549,14 +564,14 @@ void EEVEE_volumes_resolve(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda
e_data.depth_src = dtxl->depth;
/* Step 4: Apply for opaque */
- DRW_framebuffer_bind(fbl->effect_fb);
+ GPU_framebuffer_bind(fbl->effect_color_fb);
DRW_draw_pass(psl->volumetric_resolve_ps);
/* Swap the buffers and rebind depth to the current buffer */
- DRW_framebuffer_texture_detach(dtxl->depth);
- SWAP(struct GPUFrameBuffer *, fbl->main, fbl->effect_fb);
+ SWAP(GPUFrameBuffer *, fbl->main_fb, fbl->effect_fb);
+ SWAP(GPUFrameBuffer *, fbl->main_color_fb, fbl->effect_color_fb);
SWAP(GPUTexture *, txl->color, txl->color_post);
- DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
+ GPU_framebuffer_texture_attach(fbl->main_fb, dtxl->depth, 0, 0);
}
}
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index 68299fe7546..77c873c1503 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -8,12 +8,7 @@
#define LUT_SIZE 64
-uniform mat4 ProjectionMatrix;
-uniform mat4 ViewProjectionMatrix;
-uniform mat4 ViewMatrixInverse;
-#ifndef SHADOW_SHADER
-uniform mat4 ViewMatrix;
-#else
+#ifdef SHADOW_SHADER
layout(std140) uniform shadow_render_block {
mat4 ShadowMatrix[6];
mat4 FaceViewMatrix[6];
@@ -27,7 +22,21 @@ layout(std140) uniform shadow_render_block {
};
flat in int shFace; /* Shadow layer we are rendering to. */
-#define ViewMatrix FaceViewMatrix[shFace]
+
+/* Replacing viewBlock */
+#define ViewMatrix FaceViewMatrix[shFace]
+#define ViewProjectionMatrix ShadowMatrix[shFace]
+/* TODO optimize */
+#define ProjectionMatrix \
+mat4(vec4(1.0, 0.0, 0.0, 0.0), \
+ vec4(0.0, 1.0, 0.0, 0.0), \
+ vec4(0.0, 0.0, -(farClip + nearClip) / (farClip - nearClip), -1.0), \
+ vec4(0.0, 0.0, (-2.0 * farClip * nearClip) / (farClip - nearClip), 0.0))
+
+#define ViewMatrixInverse inverse(ViewMatrix)
+#define ViewProjectionMatrixInverse inverse(ViewProjectionMatrix)
+#define ProjectionMatrixInverse inverse(ProjectionMatrix)
+#define CameraTexCoFactors vec4(1.0f, 1.0f, 0.0f, 0.0f)
#endif
/* Buffers */
@@ -325,7 +334,7 @@ vec2 get_uvs_from_view(vec3 view)
vec3 get_view_space_from_depth(vec2 uvcoords, float depth)
{
if (ProjectionMatrix[3][3] == 0.0) {
- return (viewVecs[0].xyz + vec3(uvcoords, 0.0) * viewVecs[1].xyz) * get_view_z_from_depth(depth);
+ return vec3(viewVecs[0].xy + uvcoords * viewVecs[1].xy, 1.0) * get_view_z_from_depth(depth);
}
else {
return viewVecs[0].xyz + vec3(uvcoords, depth) * viewVecs[1].xyz;
@@ -418,19 +427,19 @@ float get_btdf_lut(sampler2DArray btdf_lut_tex, float NV, float roughness, float
* Using Method #4: Spheremap Transform */
vec2 normal_encode(vec3 n, vec3 view)
{
- float p = sqrt(n.z * 8.0 + 8.0);
- return n.xy / p + 0.5;
+ float p = sqrt(n.z * 8.0 + 8.0);
+ return n.xy / p + 0.5;
}
vec3 normal_decode(vec2 enc, vec3 view)
{
- vec2 fenc = enc * 4.0 - 2.0;
- float f = dot(fenc, fenc);
- float g = sqrt(1.0 - f / 4.0);
- vec3 n;
- n.xy = fenc*g;
- n.z = 1 - f / 2;
- return n;
+ vec2 fenc = enc * 4.0 - 2.0;
+ float f = dot(fenc, fenc);
+ float g = sqrt(1.0 - f / 4.0);
+ vec3 n;
+ n.xy = fenc*g;
+ n.z = 1 - f / 2;
+ return n;
}
/* ---- RGBM (shared multiplier) encoding ---- */
@@ -654,12 +663,12 @@ Closure closure_add(Closure cl1, Closure cl2)
struct Closure {
vec3 radiance;
float opacity;
-#ifdef USE_SSS
+# ifdef USE_SSS
vec4 sss_data;
-#ifdef USE_SSS_ALBEDO
+# ifdef USE_SSS_ALBEDO
vec3 sss_albedo;
-#endif
-#endif
+# endif
+# endif
vec4 ssr_data;
vec2 ssr_normal;
int ssr_id;
@@ -669,15 +678,15 @@ struct Closure {
#define TRANSPARENT_CLOSURE_FLAG -2
#define REFRACT_CLOSURE_FLAG -3
-#ifdef USE_SSS
-#ifdef USE_SSS_ALBEDO
+# ifdef USE_SSS
+# ifdef USE_SSS_ALBEDO
#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec3(0.0), vec4(0.0), vec2(0.0), -1)
-#else
+# else
#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec4(0.0), vec2(0.0), -1)
-#endif
-#else
+# endif
+# else
#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec2(0.0), -1)
-#endif
+# endif
uniform int outputSsrId;
@@ -685,45 +694,51 @@ Closure closure_mix(Closure cl1, Closure cl2, float fac)
{
Closure cl;
- if (cl1.ssr_id == outputSsrId) {
- cl.ssr_data = mix(cl1.ssr_data.xyzw, vec4(vec3(0.0), cl1.ssr_data.w), fac); /* do not blend roughness */
- cl.ssr_normal = cl1.ssr_normal;
- cl.ssr_id = cl1.ssr_id;
- }
- else {
- cl.ssr_data = mix(vec4(vec3(0.0), cl2.ssr_data.w), cl2.ssr_data.xyzw, fac); /* do not blend roughness */
- cl.ssr_normal = cl2.ssr_normal;
- cl.ssr_id = cl2.ssr_id;
- }
if (cl1.ssr_id == TRANSPARENT_CLOSURE_FLAG) {
cl1.radiance = cl2.radiance;
-#ifdef USE_SSS
+ cl1.ssr_normal = cl2.ssr_normal;
+ cl1.ssr_data = cl2.ssr_data;
+ cl1.ssr_id = cl2.ssr_id;
+# ifdef USE_SSS
cl1.sss_data = cl2.sss_data;
-#ifdef USE_SSS_ALBEDO
+# ifdef USE_SSS_ALBEDO
cl1.sss_albedo = cl2.sss_albedo;
-#endif
-#endif
+# endif
+# endif
}
if (cl2.ssr_id == TRANSPARENT_CLOSURE_FLAG) {
cl2.radiance = cl1.radiance;
-#ifdef USE_SSS
+ cl2.ssr_normal = cl1.ssr_normal;
+ cl2.ssr_data = cl1.ssr_data;
+ cl2.ssr_id = cl1.ssr_id;
+# ifdef USE_SSS
cl2.sss_data = cl1.sss_data;
-#ifdef USE_SSS_ALBEDO
+# ifdef USE_SSS_ALBEDO
cl2.sss_albedo = cl1.sss_albedo;
-#endif
-#endif
+# endif
+# endif
+ }
+ if (cl1.ssr_id == outputSsrId) {
+ cl.ssr_data = mix(cl1.ssr_data.xyzw, vec4(vec3(0.0), cl1.ssr_data.w), fac); /* do not blend roughness */
+ cl.ssr_normal = cl1.ssr_normal;
+ cl.ssr_id = cl1.ssr_id;
+ }
+ else {
+ cl.ssr_data = mix(vec4(vec3(0.0), cl2.ssr_data.w), cl2.ssr_data.xyzw, fac); /* do not blend roughness */
+ cl.ssr_normal = cl2.ssr_normal;
+ cl.ssr_id = cl2.ssr_id;
}
cl.radiance = mix(cl1.radiance, cl2.radiance, fac);
cl.opacity = mix(cl1.opacity, cl2.opacity, fac);
-#ifdef USE_SSS
+# ifdef USE_SSS
cl.sss_data.rgb = mix(cl1.sss_data.rgb, cl2.sss_data.rgb, fac);
cl.sss_data.a = (cl1.sss_data.a > 0.0) ? cl1.sss_data.a : cl2.sss_data.a;
-#ifdef USE_SSS_ALBEDO
+# ifdef USE_SSS_ALBEDO
/* TODO Find a solution to this. Dither? */
cl.sss_albedo = (cl1.sss_data.a > 0.0) ? cl1.sss_albedo : cl2.sss_albedo;
-#endif
-#endif
+# endif
+# endif
return cl;
}
@@ -731,80 +746,73 @@ Closure closure_mix(Closure cl1, Closure cl2, float fac)
Closure closure_add(Closure cl1, Closure cl2)
{
Closure cl = (cl1.ssr_id == outputSsrId) ? cl1 : cl2;
-#ifdef USE_SSS
+# ifdef USE_SSS
cl.sss_data = (cl1.sss_data.a > 0.0) ? cl1.sss_data : cl2.sss_data;
-#ifdef USE_SSS_ALBEDO
+# ifdef USE_SSS_ALBEDO
/* TODO Find a solution to this. Dither? */
cl.sss_albedo = (cl1.sss_data.a > 0.0) ? cl1.sss_albedo : cl2.sss_albedo;
-#endif
-#endif
+# endif
+# endif
cl.radiance = cl1.radiance + cl2.radiance;
cl.opacity = saturate(cl1.opacity + cl2.opacity);
return cl;
}
-#if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER) && !defined(USE_MULTIPLY)
+# if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER) && !defined(USE_MULTIPLY)
layout(location = 0) out vec4 fragColor;
-#ifdef USE_SSS
-#ifdef USE_SSS_ALBEDO
-layout(location = 1) out vec4 sssData;
-layout(location = 2) out vec4 sssAlbedo;
-layout(location = 3) out vec4 ssrNormals;
-layout(location = 4) out vec4 ssrData;
-#else
-layout(location = 1) out vec4 sssData;
-layout(location = 2) out vec4 ssrNormals;
-layout(location = 3) out vec4 ssrData;
-#endif /* USE_SSS_ALBEDO */
-#else
layout(location = 1) out vec4 ssrNormals;
layout(location = 2) out vec4 ssrData;
-#endif /* USE_SSS */
+# ifdef USE_SSS
+layout(location = 3) out vec4 sssData;
+# ifdef USE_SSS_ALBEDO
+layout(location = 4) out vec4 sssAlbedo;
+# endif /* USE_SSS_ALBEDO */
+# endif /* USE_SSS */
Closure nodetree_exec(void); /* Prototype */
-#if defined(USE_ALPHA_BLEND_VOLUMETRICS)
+# if defined(USE_ALPHA_BLEND_VOLUMETRICS)
/* Prototype because this file is included before volumetric_lib.glsl */
vec4 volumetric_resolve(vec4 scene_color, vec2 frag_uvs, float frag_depth);
-#endif
+# endif
#define NODETREE_EXEC
void main()
{
Closure cl = nodetree_exec();
-#ifndef USE_ALPHA_BLEND
+# ifndef USE_ALPHA_BLEND
/* Prevent alpha hash material writing into alpha channel. */
cl.opacity = 1.0;
-#endif
+# endif
-#if defined(USE_ALPHA_BLEND_VOLUMETRICS)
+# if defined(USE_ALPHA_BLEND_VOLUMETRICS)
/* XXX fragile, better use real viewport resolution */
vec2 uvs = gl_FragCoord.xy / vec2(2 * textureSize(maxzBuffer, 0).xy);
fragColor = volumetric_resolve(vec4(cl.radiance, cl.opacity), uvs, gl_FragCoord.z);
-#else
+# else
fragColor = vec4(cl.radiance, cl.opacity);
-#endif
+# endif
ssrNormals = cl.ssr_normal.xyyy;
ssrData = cl.ssr_data;
-#ifdef USE_SSS
+# ifdef USE_SSS
sssData = cl.sss_data;
-#ifdef USE_SSS_ALBEDO
+# ifdef USE_SSS_ALBEDO
sssAlbedo = cl.sss_albedo.rgbb;
-#endif
-#endif
+# endif
+# endif
/* For Probe capture */
-#ifdef USE_SSS
-#ifdef USE_SSS_ALBEDO
+# ifdef USE_SSS
+# ifdef USE_SSS_ALBEDO
fragColor.rgb += cl.sss_data.rgb * cl.sss_albedo.rgb * float(!sssToggle);
-#else
+# else
fragColor.rgb += cl.sss_data.rgb * float(!sssToggle);
-#endif
-#endif
+# endif
+# endif
}
-#endif /* MESH_SHADER && !SHADOW_SHADER */
+# endif /* MESH_SHADER && !SHADOW_SHADER */
#endif /* VOLUMETRICS */
diff --git a/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl
index 32edf709d88..b7bcf5c8a8b 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl
@@ -28,7 +28,8 @@ void main()
gtao_deferred(normal, viewPosition, noise, depth, visibility, bent_normal);
- FragColor = vec4(visibility);
+ /* Handle Background case. Prevent artifact due to uncleared Horizon Render Target. */
+ FragColor = vec4((depth == 1.0) ? 0.0 : visibility);
}
#else
diff --git a/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl
index 65d3970a82a..05fef73b159 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl
@@ -23,7 +23,9 @@ uniform sampler2D depthBuffer;
#define minmax(a, b) max(a, b)
#endif
-#ifdef GPU_INTEL
+/* On some AMD card / driver conbination, it is needed otherwise,
+ * the shader does not write anything. */
+#if defined(GPU_INTEL) || defined(GPU_ATI)
out vec4 fragColor;
#endif
@@ -65,10 +67,9 @@ void main()
}
#endif
-#ifdef GPU_INTEL
+#if defined(GPU_INTEL) || defined(GPU_ATI)
/* Use color format instead of 24bit depth texture */
fragColor = vec4(val);
-#else
- gl_FragDepth = val;
#endif
+ gl_FragDepth = val;
} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl
new file mode 100644
index 00000000000..fe38b2e9aac
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl
@@ -0,0 +1,31 @@
+/* Convert depth to Mist factor */
+uniform vec3 mistSettings;
+
+#define mistStart mistSettings.x
+#define mistInvDistance mistSettings.y
+#define mistFalloff mistSettings.z
+
+out vec4 fragColor;
+
+void main()
+{
+ vec2 texel_size = 1.0 / vec2(textureSize(depthBuffer, 0)).xy;
+ vec2 uvs = gl_FragCoord.xy * texel_size;
+
+ float depth = textureLod(depthBuffer, uvs, 0.0).r;
+ vec3 co = get_view_space_from_depth(uvs, depth);
+
+ float zcor = (ProjectionMatrix[3][3] == 0.0) ? length(co) : -co.z;
+
+ /* bring depth into 0..1 range */
+ float mist = saturate((zcor - mistStart) * mistInvDistance);
+
+ /* falloff */
+ mist = pow(mist, mistFalloff);
+
+ fragColor = vec4(mist);
+
+ // if (mist > 0.999) fragColor = vec4(1.0);
+ // else if (mist > 0.0001) fragColor = vec4(0.5);
+ // else fragColor = vec4(0.0);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
index 184eac54c26..5ecf6323255 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
@@ -18,9 +18,10 @@ uniform sampler2DArray utilTex;
#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
#endif /* UTIL_TEX */
-out vec4 FragColor;
-
-uniform mat4 ProjectionMatrix;
+layout(location = 0) out vec4 FragColor;
+#ifdef RESULT_ACCUM
+layout(location = 1) out vec4 sssColor;
+#endif
float get_view_z_from_depth(float depth)
{
@@ -84,10 +85,15 @@ void main(void)
#ifdef FIRST_PASS
FragColor = vec4(accum, sss_data.a);
#else /* SECOND_PASS */
- #ifdef USE_SEP_ALBEDO
+# ifdef USE_SEP_ALBEDO
+# ifdef RESULT_ACCUM
+ FragColor = vec4(accum, 1.0);
+ sssColor = texture(sssAlbedo, uvs);
+# else
FragColor = vec4(accum * texture(sssAlbedo, uvs).rgb, 1.0);
- #else
+# endif
+# else
FragColor = vec4(accum, 1.0);
- #endif
+# endif
#endif
}
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl
index 202b27be0ef..57da4d0d1ec 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl
@@ -6,8 +6,6 @@ in int probe_id;
in vec3 probe_location;
in float sphere_size;
-uniform mat4 ViewProjectionMatrix;
-
flat out int pid;
out vec3 worldNormal;
out vec3 worldPosition;
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl
index fd200ec5984..37f73714a8e 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl
@@ -1,8 +1,6 @@
in vec3 pos;
-uniform mat4 ViewProjectionMatrix;
-
uniform float sphere_size;
uniform int offset;
uniform ivec3 grid_resolution;
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl
index 655cc626bba..3808b59761f 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl
@@ -1,5 +1,4 @@
-uniform mat4 ViewProjectionMatrix;
uniform sampler2DArray probePlanars;
in vec3 worldPosition;
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_vert.glsl
index a9716332eb5..3ecd85fd72e 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_vert.glsl
@@ -4,8 +4,6 @@ in vec3 pos;
in int probe_id;
in mat4 probe_mat;
-uniform mat4 ViewProjectionMatrix;
-
out vec3 worldPosition;
flat out int probeIdx;
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl
index 40b04c986f3..23c16f0fa30 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl
@@ -11,13 +11,13 @@ void main() {
gl_Layer = instance[0];
layer = float(instance[0]);
- gl_Position = vec4(vPos[0], 0.0, 0.0);
+ gl_Position = vec4(vPos[0], 0.0, 1.0);
EmitVertex();
- gl_Position = vec4(vPos[1], 0.0, 0.0);
+ gl_Position = vec4(vPos[1], 0.0, 1.0);
EmitVertex();
- gl_Position = vec4(vPos[2], 0.0, 0.0);
+ gl_Position = vec4(vPos[2], 0.0, 1.0);
EmitVertex();
EndPrimitive();
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
index fd7f3870d27..d53852193d5 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
@@ -19,7 +19,10 @@ out vec3 worldPosition;
out vec3 viewPosition;
/* Used for planar reflections */
-uniform vec4 ClipPlanes[1];
+/* keep in sync with EEVEE_ClipPlanesUniformBuffer */
+layout(std140) uniform clip_block {
+ vec4 ClipPlanes[1];
+};
#ifdef USE_FLAT_NORMAL
flat out vec3 worldNormal;
diff --git a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
index 1b53e503003..974c5724842 100644
--- a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
@@ -2,9 +2,11 @@
uniform mat4 ModelViewProjectionMatrix;
uniform mat4 ModelMatrix;
uniform mat4 ModelViewMatrix;
-#ifdef CLIP_PLANES
-uniform vec4 ClipPlanes[1];
-#endif
+
+/* keep in sync with DRWManager.view_data */
+layout(std140) uniform clip_block {
+ vec4 ClipPlanes[1];
+};
#ifndef HAIR_SHADER_FIBERS
in vec3 pos;
@@ -28,7 +30,7 @@ void main()
#ifdef CLIP_PLANES
vec4 worldPosition = (ModelMatrix * vec4(pos, 1.0));
- gl_ClipDistance[0] = dot(worldPosition, ClipPlanes[0]);
+ gl_ClipDistance[0] = dot(vec4(worldPosition.xyz, 1.0), ClipPlanes[0]);
#endif
/* TODO motion vectors */
}
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl
index fcc304ca289..0fc7e4c9396 100644
--- a/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl
@@ -47,7 +47,7 @@ vec4 ln_space_prefilter(float w0, vec4 x, float w1, vec4 y)
}
#ifdef CSM
-vec3 get_texco(vec3 cos, vec2 ofs)
+vec3 get_texco(vec3 cos, const vec2 ofs)
{
cos.xy += ofs * shadowFilterSize;
return cos;
@@ -64,13 +64,43 @@ void make_orthonormal_basis(vec3 N)
B = cross(N, T);
}
-vec3 get_texco(vec3 cos, vec2 ofs)
+vec3 get_texco(vec3 cos, const vec2 ofs)
{
return cos + ofs.x * T + ofs.y * B;
}
#endif
+#ifdef ESM
+void grouped_samples_accum(
+ vec3 cos,
+ const vec2 co1, const vec2 co2, const vec2 co3, const vec2 co4,
+ inout vec4 accum)
+{
+ vec4 depths;
+ depths.x = texture(shadowTexture, get_texco(cos, co1)).r;
+ depths.y = texture(shadowTexture, get_texco(cos, co2)).r;
+ depths.z = texture(shadowTexture, get_texco(cos, co3)).r;
+ depths.w = texture(shadowTexture, get_texco(cos, co4)).r;
+
+ accum = ln_space_prefilter(1.0, accum, shadowInvSampleCount, depths);
+}
+#else /* VSM */
+void grouped_samples_accum(
+ vec3 cos,
+ const vec2 co1, const vec2 co2, const vec2 co3, const vec2 co4,
+ inout vec2 accum)
+{
+ vec4 depths1, depths2;
+ depths1.xy = texture(shadowTexture, get_texco(cos, co1)).rg;
+ depths1.zw = texture(shadowTexture, get_texco(cos, co2)).rg;
+ depths2.xy = texture(shadowTexture, get_texco(cos, co3)).rg;
+ depths2.zw = texture(shadowTexture, get_texco(cos, co4)).rg;
+
+ accum += depths1.xy + depths1.zw + depths2.xy + depths2.zw;
+}
+#endif
+
void main() {
vec3 cos;
@@ -105,9 +135,8 @@ void main() {
#endif
#ifdef ESM
- vec4 accum = vec4(0.0);
-
/* disc blur in log space. */
+ vec4 accum = vec4(0.0);
vec4 depths;
depths.x = texture(shadowTexture, get_texco(cos, concentric[0])).r;
depths.y = texture(shadowTexture, get_texco(cos, concentric[1])).r;
@@ -115,32 +144,102 @@ void main() {
depths.w = texture(shadowTexture, get_texco(cos, concentric[3])).r;
accum = ln_space_prefilter(0.0, accum, shadowInvSampleCount, depths);
- for (int i = 4; i < shadowSampleCount && i < CONCENTRIC_SAMPLE_NUM; i += 4) {
- depths.x = texture(shadowTexture, get_texco(cos, concentric[i+0])).r;
- depths.y = texture(shadowTexture, get_texco(cos, concentric[i+1])).r;
- depths.z = texture(shadowTexture, get_texco(cos, concentric[i+2])).r;
- depths.w = texture(shadowTexture, get_texco(cos, concentric[i+3])).r;
- accum = ln_space_prefilter(1.0, accum, shadowInvSampleCount, depths);
+#else /* VSM */
+ vec2 accum = vec2(0.0);
+ grouped_samples_accum(cos, concentric[0], concentric[1], concentric[2], concentric[3], accum);
+#endif
+
+ /**
+ * Making the `grouped_samples_accum` be called within a loop would be
+ * the most conventional solution, however in some older gpus, transverse the huge
+ * `const vec2 concentric[]` array with variable indices is extremely slow.
+ * The solution is to use constant indices to access the array.
+ */
+ if (shadowSampleCount > 4) {
+ grouped_samples_accum(cos, concentric[4], concentric[5], concentric[6], concentric[7], accum);
+ grouped_samples_accum(cos, concentric[8], concentric[9], concentric[10], concentric[11], accum);
+ grouped_samples_accum(cos, concentric[12], concentric[13], concentric[14], concentric[15], accum);
+ }
+ if (shadowSampleCount > 16) {
+ grouped_samples_accum(cos, concentric[16], concentric[17], concentric[18], concentric[19], accum);
+ grouped_samples_accum(cos, concentric[20], concentric[21], concentric[22], concentric[23], accum);
+ grouped_samples_accum(cos, concentric[24], concentric[25], concentric[26], concentric[27], accum);
+ grouped_samples_accum(cos, concentric[28], concentric[29], concentric[30], concentric[31], accum);
+ grouped_samples_accum(cos, concentric[32], concentric[33], concentric[34], concentric[35], accum);
+ }
+ if (shadowSampleCount > 36) {
+ grouped_samples_accum(cos, concentric[36], concentric[37], concentric[38], concentric[39], accum);
+ grouped_samples_accum(cos, concentric[40], concentric[41], concentric[42], concentric[43], accum);
+ grouped_samples_accum(cos, concentric[44], concentric[45], concentric[46], concentric[47], accum);
+ grouped_samples_accum(cos, concentric[48], concentric[49], concentric[50], concentric[51], accum);
+ grouped_samples_accum(cos, concentric[52], concentric[53], concentric[54], concentric[55], accum);
+ grouped_samples_accum(cos, concentric[56], concentric[57], concentric[58], concentric[59], accum);
+ grouped_samples_accum(cos, concentric[60], concentric[61], concentric[62], concentric[63], accum);
+ }
+ if (shadowSampleCount > 64) {
+ grouped_samples_accum(cos, concentric[64], concentric[65], concentric[66], concentric[67], accum);
+ grouped_samples_accum(cos, concentric[68], concentric[69], concentric[70], concentric[71], accum);
+ grouped_samples_accum(cos, concentric[72], concentric[73], concentric[74], concentric[75], accum);
+ grouped_samples_accum(cos, concentric[76], concentric[77], concentric[78], concentric[79], accum);
+ grouped_samples_accum(cos, concentric[80], concentric[81], concentric[82], concentric[83], accum);
+ grouped_samples_accum(cos, concentric[84], concentric[85], concentric[86], concentric[87], accum);
+ grouped_samples_accum(cos, concentric[88], concentric[89], concentric[90], concentric[91], accum);
+ grouped_samples_accum(cos, concentric[92], concentric[93], concentric[94], concentric[95], accum);
+ grouped_samples_accum(cos, concentric[96], concentric[97], concentric[98], concentric[99], accum);
+ }
+ if (shadowSampleCount > 100) {
+ grouped_samples_accum(cos, concentric[100], concentric[101], concentric[102], concentric[103], accum);
+ grouped_samples_accum(cos, concentric[104], concentric[105], concentric[106], concentric[107], accum);
+ grouped_samples_accum(cos, concentric[108], concentric[109], concentric[110], concentric[111], accum);
+ grouped_samples_accum(cos, concentric[112], concentric[113], concentric[114], concentric[115], accum);
+ grouped_samples_accum(cos, concentric[116], concentric[117], concentric[118], concentric[119], accum);
+ grouped_samples_accum(cos, concentric[120], concentric[121], concentric[122], concentric[123], accum);
+ grouped_samples_accum(cos, concentric[124], concentric[125], concentric[126], concentric[127], accum);
+ grouped_samples_accum(cos, concentric[128], concentric[129], concentric[130], concentric[131], accum);
+ grouped_samples_accum(cos, concentric[132], concentric[133], concentric[134], concentric[135], accum);
+ grouped_samples_accum(cos, concentric[136], concentric[137], concentric[138], concentric[139], accum);
+ grouped_samples_accum(cos, concentric[140], concentric[141], concentric[142], concentric[143], accum);
+ }
+ if (shadowSampleCount > 144) {
+ grouped_samples_accum(cos, concentric[144], concentric[145], concentric[146], concentric[147], accum);
+ grouped_samples_accum(cos, concentric[148], concentric[149], concentric[150], concentric[151], accum);
+ grouped_samples_accum(cos, concentric[152], concentric[153], concentric[154], concentric[155], accum);
+ grouped_samples_accum(cos, concentric[156], concentric[157], concentric[158], concentric[159], accum);
+ grouped_samples_accum(cos, concentric[160], concentric[161], concentric[162], concentric[163], accum);
+ grouped_samples_accum(cos, concentric[164], concentric[165], concentric[166], concentric[167], accum);
+ grouped_samples_accum(cos, concentric[168], concentric[169], concentric[170], concentric[171], accum);
+ grouped_samples_accum(cos, concentric[172], concentric[173], concentric[174], concentric[175], accum);
+ grouped_samples_accum(cos, concentric[176], concentric[177], concentric[178], concentric[179], accum);
+ grouped_samples_accum(cos, concentric[180], concentric[181], concentric[182], concentric[183], accum);
+ grouped_samples_accum(cos, concentric[184], concentric[185], concentric[186], concentric[187], accum);
+ grouped_samples_accum(cos, concentric[188], concentric[189], concentric[190], concentric[191], accum);
+ grouped_samples_accum(cos, concentric[192], concentric[193], concentric[194], concentric[195], accum);
+ }
+ if (shadowSampleCount > 196) {
+ grouped_samples_accum(cos, concentric[196], concentric[197], concentric[198], concentric[199], accum);
+ grouped_samples_accum(cos, concentric[200], concentric[201], concentric[202], concentric[203], accum);
+ grouped_samples_accum(cos, concentric[204], concentric[205], concentric[206], concentric[207], accum);
+ grouped_samples_accum(cos, concentric[208], concentric[209], concentric[210], concentric[211], accum);
+ grouped_samples_accum(cos, concentric[212], concentric[213], concentric[114], concentric[215], accum);
+ grouped_samples_accum(cos, concentric[216], concentric[217], concentric[218], concentric[219], accum);
+ grouped_samples_accum(cos, concentric[220], concentric[221], concentric[222], concentric[223], accum);
+ grouped_samples_accum(cos, concentric[224], concentric[225], concentric[226], concentric[227], accum);
+ grouped_samples_accum(cos, concentric[228], concentric[229], concentric[230], concentric[231], accum);
+ grouped_samples_accum(cos, concentric[232], concentric[233], concentric[234], concentric[235], accum);
+ grouped_samples_accum(cos, concentric[236], concentric[237], concentric[238], concentric[239], accum);
+ grouped_samples_accum(cos, concentric[240], concentric[241], concentric[242], concentric[243], accum);
+ grouped_samples_accum(cos, concentric[244], concentric[245], concentric[246], concentric[247], accum);
+ grouped_samples_accum(cos, concentric[248], concentric[249], concentric[250], concentric[251], accum);
+ grouped_samples_accum(cos, concentric[252], concentric[253], concentric[254], concentric[255], accum);
}
+#ifdef ESM
accum.x = ln_space_prefilter(1.0, accum.x, 1.0, accum.y);
accum.x = ln_space_prefilter(1.0, accum.x, 1.0, accum.z);
accum.x = ln_space_prefilter(1.0, accum.x, 1.0, accum.w);
FragColor = accum.xxxx;
#else /* VSM */
- vec2 accum = vec2(0.0);
-
- /* disc blur. */
- vec4 depths1, depths2;
- for (int i = 0; i < shadowSampleCount && i < CONCENTRIC_SAMPLE_NUM; i += 4) {
- depths1.xy = texture(shadowTexture, get_texco(cos, concentric[i+0])).rg;
- depths1.zw = texture(shadowTexture, get_texco(cos, concentric[i+1])).rg;
- depths2.xy = texture(shadowTexture, get_texco(cos, concentric[i+2])).rg;
- depths2.zw = texture(shadowTexture, get_texco(cos, concentric[i+3])).rg;
- accum += depths1.xy + depths1.zw + depths2.xy + depths2.zw;
- }
-
FragColor = accum.xyxy * shadowInvSampleCount;
#endif
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
index 777902ccba8..29cbcfdd6e4 100644
--- a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
@@ -1,5 +1,5 @@
-uniform mat4 ShadowModelMatrix;
+uniform mat4 ModelMatrix;
#ifdef MESH_SHADER
uniform mat3 WorldNormalMatrix;
#endif
@@ -17,7 +17,7 @@ out vec3 vNor;
flat out int face;
void main() {
- vPos = ShadowModelMatrix * vec4(pos, 1.0);
+ vPos = ModelMatrix * vec4(pos, 1.0);
face = gl_InstanceID;
#ifdef MESH_SHADER
diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c
index 851d0ef9eb7..ec0141953fe 100644
--- a/source/blender/draw/engines/external/external_engine.c
+++ b/source/blender/draw/engines/external/external_engine.c
@@ -218,6 +218,7 @@ DrawEngineType draw_engine_external_type = {
&external_draw_scene,
NULL,
NULL,
+ NULL,
};
/* Note: currently unused, we should not register unless we want to see this when debugging the view. */
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 1f16f63ba14..60e855108f9 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -45,6 +45,8 @@
#include "DNA_material_types.h"
#include "DNA_scene_types.h"
+#include "GPU_framebuffer.h"
+
#include "draw_common.h"
#include "draw_cache.h"
#include "draw_view.h"
@@ -55,6 +57,9 @@
#include "RE_engine.h"
+#include "DEG_depsgraph.h"
+
+struct rcti;
struct bContext;
struct GPUFrameBuffer;
struct GPUShader;
@@ -76,6 +81,11 @@ typedef struct DRWInterface DRWInterface;
typedef struct DRWPass DRWPass;
typedef struct DRWShadingGroup DRWShadingGroup;
+/* TODO Put it somewhere else? */
+typedef struct BoundSphere {
+ float center[3], radius;
+} BoundSphere;
+
/* declare members as empty (unused) */
typedef char DRWViewportEmptyList;
@@ -94,9 +104,8 @@ typedef char DRWViewportEmptyList;
#define MULTISAMPLE_SYNC_ENABLE(dfbl) { \
if (dfbl->multisample_fb != NULL) { \
DRW_stats_query_start("Multisample Blit"); \
- DRW_framebuffer_blit(dfbl->default_fb, dfbl->multisample_fb, false, false); \
- DRW_framebuffer_blit(dfbl->default_fb, dfbl->multisample_fb, true, false); \
- DRW_framebuffer_bind(dfbl->multisample_fb); \
+ GPU_framebuffer_blit(dfbl->default_fb, 0, dfbl->multisample_fb, 0, GPU_COLOR_BIT | GPU_DEPTH_BIT); \
+ GPU_framebuffer_bind(dfbl->multisample_fb); \
DRW_stats_query_end(); \
} \
}
@@ -104,9 +113,8 @@ typedef char DRWViewportEmptyList;
#define MULTISAMPLE_SYNC_DISABLE(dfbl) { \
if (dfbl->multisample_fb != NULL) { \
DRW_stats_query_start("Multisample Resolve"); \
- DRW_framebuffer_blit(dfbl->multisample_fb, dfbl->default_fb, false, false); \
- DRW_framebuffer_blit(dfbl->multisample_fb, dfbl->default_fb, true, false); \
- DRW_framebuffer_bind(dfbl->default_fb); \
+ GPU_framebuffer_blit(dfbl->multisample_fb, 0, dfbl->default_fb, 0, GPU_COLOR_BIT | GPU_DEPTH_BIT); \
+ GPU_framebuffer_bind(dfbl->default_fb); \
DRW_stats_query_end(); \
} \
}
@@ -139,12 +147,16 @@ typedef struct DrawEngineType {
void (*view_update)(void *vedata);
void (*id_update)(void *vedata, struct ID *id);
+
+ void (*render_to_image)(void *vedata, struct RenderEngine *engine, struct RenderLayer *layer, const struct rcti *rect);
} DrawEngineType;
#ifndef __DRW_ENGINE_H__
/* Buffer and textures used by the viewport by default */
typedef struct DefaultFramebufferList {
struct GPUFrameBuffer *default_fb;
+ struct GPUFrameBuffer *color_only_fb;
+ struct GPUFrameBuffer *depth_only_fb;
struct GPUFrameBuffer *multisample_fb;
} DefaultFramebufferList;
@@ -174,6 +186,7 @@ typedef enum {
DRW_TEX_RG_32,
DRW_TEX_R_8,
DRW_TEX_R_16,
+ DRW_TEX_R_16I,
DRW_TEX_R_32,
DRW_TEX_DEPTH_16,
DRW_TEX_DEPTH_24,
@@ -186,9 +199,13 @@ typedef enum {
DRW_TEX_WRAP = (1 << 1),
DRW_TEX_COMPARE = (1 << 2),
DRW_TEX_MIPMAP = (1 << 3),
- DRW_TEX_TEMP = (1 << 4),
} DRWTextureFlag;
+/* Textures from DRW_texture_pool_query_* have the options
+ * DRW_TEX_FILTER for color float textures, and no options
+ * for depth textures and integer textures. */
+struct GPUTexture *DRW_texture_pool_query_2D(int w, int h, DRWTextureFormat format, DrawEngineType *engine_type);
+
struct GPUTexture *DRW_texture_create_1D(
int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
struct GPUTexture *DRW_texture_create_2D(
@@ -199,8 +216,13 @@ struct GPUTexture *DRW_texture_create_3D(
int w, int h, int d, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
struct GPUTexture *DRW_texture_create_cube(
int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
+
+void DRW_texture_ensure_fullscreen_2D(
+ struct GPUTexture **tex, DRWTextureFormat format, DRWTextureFlag flags);
+void DRW_texture_ensure_2D(
+ struct GPUTexture **tex, int w, int h, DRWTextureFormat format, DRWTextureFlag flags);
+
void DRW_texture_generate_mipmaps(struct GPUTexture *tex);
-void DRW_texture_update(struct GPUTexture *tex, const float *pixels);
void DRW_texture_free(struct GPUTexture *tex);
#define DRW_TEXTURE_FREE_SAFE(tex) do { \
if (tex != NULL) { \
@@ -220,39 +242,6 @@ void DRW_uniformbuffer_free(struct GPUUniformBuffer *ubo);
} \
} while (0)
-/* Buffers */
-#define MAX_FBO_TEX 5
-
-typedef struct DRWFboTexture {
- struct GPUTexture **tex;
- int format;
- DRWTextureFlag flag;
-} DRWFboTexture;
-
-struct GPUFrameBuffer *DRW_framebuffer_create(void);
-void DRW_framebuffer_init(
- struct GPUFrameBuffer **fb, void *engine_type, int width, int height,
- DRWFboTexture textures[MAX_FBO_TEX], int textures_len);
-void DRW_framebuffer_bind(struct GPUFrameBuffer *fb);
-void DRW_framebuffer_clear(bool color, bool depth, bool stencil, float clear_col[4], float clear_depth);
-void DRW_framebuffer_read_data(int x, int y, int w, int h, int channels, int slot, float *data);
-void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int mip);
-void DRW_framebuffer_texture_layer_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int layer, int mip);
-void DRW_framebuffer_cubeface_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int face, int mip);
-void DRW_framebuffer_texture_detach(struct GPUTexture *tex);
-void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer *fb_write, bool depth, bool stencil);
-void DRW_framebuffer_recursive_downsample(
- struct GPUFrameBuffer *fb, struct GPUTexture *tex, int num_iter,
- void (*callback)(void *userData, int level), void *userData);
-void DRW_framebuffer_viewport_size(struct GPUFrameBuffer *fb_read, int x, int y, int w, int h);
-void DRW_framebuffer_free(struct GPUFrameBuffer *fb);
-#define DRW_FRAMEBUFFER_FREE_SAFE(fb) do { \
- if (fb != NULL) { \
- DRW_framebuffer_free(fb); \
- fb = NULL; \
- } \
-} while (0)
-
void DRW_transform_to_display(struct GPUTexture *tex);
/* Shaders */
@@ -264,6 +253,14 @@ struct GPUShader *DRW_shader_create_2D(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_3D(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_3D_depth_only(void);
+struct GPUMaterial *DRW_shader_find_from_world(struct World *wo, const void *engine_type, int options);
+struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma, const void *engine_type, int options);
+struct GPUMaterial *DRW_shader_create_from_world(
+ struct Scene *scene, struct World *wo, const void *engine_type, int options,
+ const char *vert, const char *geom, const char *frag_lib, const char *defines);
+struct GPUMaterial *DRW_shader_create_from_material(
+ struct Scene *scene, struct Material *ma, const void *engine_type, int options,
+ const char *vert, const char *geom, const char *frag_lib, const char *defines);
void DRW_shader_free(struct GPUShader *shader);
#define DRW_SHADER_FREE_SAFE(shader) do { \
if (shader != NULL) { \
@@ -284,7 +281,7 @@ typedef enum {
DRW_STATE_CULL_BACK = (1 << 6),
DRW_STATE_CULL_FRONT = (1 << 7),
DRW_STATE_WIRE = (1 << 8),
- DRW_STATE_WIRE_LARGE = (1 << 9),
+// DRW_STATE_WIRE_LARGE = (1 << 9), /* Removed from ogl in 3.0 */
DRW_STATE_POINT = (1 << 10),
DRW_STATE_STIPPLE_2 = (1 << 11),
DRW_STATE_STIPPLE_3 = (1 << 12),
@@ -302,13 +299,33 @@ typedef enum {
#define DRW_STATE_DEFAULT (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS)
+typedef enum {
+ DRW_ATTRIB_INT,
+ DRW_ATTRIB_FLOAT,
+} DRWAttribType;
+
+typedef struct DRWInstanceAttribFormat {
+ char name[32];
+ DRWAttribType type;
+ int components;
+} DRWInstanceAttribFormat;
+
+struct Gwn_VertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttribFormat attribs[], int arraysize);
+#define DRW_shgroup_instance_format(format, ...) do { \
+ if (format == NULL) { \
+ DRWInstanceAttribFormat drw_format[] = __VA_ARGS__;\
+ format = DRW_shgroup_instance_format_array(drw_format, (sizeof(drw_format) / sizeof(DRWInstanceAttribFormat))); \
+ } \
+} while (0)
DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass);
DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPass *pass);
DRWShadingGroup *DRW_shgroup_material_instance_create(
- struct GPUMaterial *material, DRWPass *pass, struct Gwn_Batch *geom, struct Object *ob);
+ struct GPUMaterial *material, DRWPass *pass, struct Gwn_Batch *geom, struct Object *ob,
+ struct Gwn_VertFormat *format);
DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(struct GPUMaterial *material, DRWPass *pass, int size);
-DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader, DRWPass *pass, struct Gwn_Batch *geom);
+DRWShadingGroup *DRW_shgroup_instance_create(
+ struct GPUShader *shader, DRWPass *pass, struct Gwn_Batch *geom, struct Gwn_VertFormat *format);
DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass);
DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass);
DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DRWPass *pass, int size);
@@ -318,11 +335,16 @@ typedef void (DRWCallGenerateFn)(
void (*draw_fn)(DRWShadingGroup *shgroup, struct Gwn_Batch *geom),
void *user_data);
-void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *instances);
+void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *batch);
void DRW_shgroup_free(struct DRWShadingGroup *shgroup);
void DRW_shgroup_call_add(DRWShadingGroup *shgroup, struct Gwn_Batch *geom, float (*obmat)[4]);
void DRW_shgroup_call_object_add(DRWShadingGroup *shgroup, struct Gwn_Batch *geom, struct Object *ob);
+/* Used for drawing a batch with instancing without instance attribs. */
+void DRW_shgroup_call_instances_add(
+ DRWShadingGroup *shgroup, struct Gwn_Batch *geom, float (*obmat)[4], unsigned int *count);
+void DRW_shgroup_call_object_instances_add(
+ DRWShadingGroup *shgroup, struct Gwn_Batch *geom, struct Object *ob, unsigned int *count);
void DRW_shgroup_call_sculpt_add(DRWShadingGroup *shgroup, struct Object *ob, float (*obmat)[4]);
void DRW_shgroup_call_generate_add(
DRWShadingGroup *shgroup, DRWCallGenerateFn *geometry_fn, void *user_data, float (*obmat)[4]);
@@ -331,17 +353,18 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *at
const void *array[] = {__VA_ARGS__}; \
DRW_shgroup_call_dynamic_add_array(shgroup, array, (sizeof(array) / sizeof(*array))); \
} while (0)
-/* Use this to set a high number of instances. */
-void DRW_shgroup_set_instance_count(DRWShadingGroup *shgroup, int count);
+
+unsigned int DRW_shgroup_get_instance_count(const DRWShadingGroup *shgroup);
void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state);
void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state);
void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, unsigned int mask);
-void DRW_shgroup_attrib_float(DRWShadingGroup *shgroup, const char *name, int size);
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const struct GPUTexture *tex);
+void DRW_shgroup_uniform_texture_persistent(DRWShadingGroup *shgroup, const char *name, const struct GPUTexture *tex);
void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const struct GPUUniformBuffer *ubo);
-void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, struct GPUTexture **tex);
+void DRW_shgroup_uniform_block_persistent(DRWShadingGroup *shgroup, const char *name, const struct GPUUniformBuffer *ubo);
+void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, struct GPUTexture **tex);
void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
@@ -370,13 +393,24 @@ typedef enum {
DRW_MAT_VIEWINV,
DRW_MAT_WIN,
DRW_MAT_WININV,
+
+ DRW_MAT_COUNT, // Don't use this.
} DRWViewportMatrixType;
+typedef struct DRWMatrixState {
+ float mat[DRW_MAT_COUNT][4][4];
+} DRWMatrixState;
+
void DRW_viewport_init(const bContext *C);
void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type);
+void DRW_viewport_matrix_get_all(DRWMatrixState *state);
void DRW_viewport_matrix_override_set(float mat[4][4], DRWViewportMatrixType type);
+void DRW_viewport_matrix_override_set_all(DRWMatrixState *state);
void DRW_viewport_matrix_override_unset(DRWViewportMatrixType type);
+void DRW_viewport_matrix_override_unset_all(void);
+
const float *DRW_viewport_size_get(void);
+const float *DRW_viewport_invert_size_get(void);
const float *DRW_viewport_screenvecs_get(void);
const float *DRW_viewport_pixelsize_get(void);
bool DRW_viewport_is_persp_get(void);
@@ -386,14 +420,24 @@ struct DefaultTextureList *DRW_viewport_texture_list_get(void);
void DRW_viewport_request_redraw(void);
+void DRW_render_to_image(struct RenderEngine *engine, struct Depsgraph *graph);
+void DRW_render_object_iter(
+ void *vedata, struct RenderEngine *engine, struct Depsgraph *graph,
+ void (*callback)(void *vedata, struct Object *ob, struct RenderEngine *engine, struct Depsgraph *graph));
+void DRW_render_instance_buffer_finish(void);
+
/* ViewLayers */
void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type);
void **DRW_view_layer_engine_data_ensure(DrawEngineType *engine_type, void (*callback)(void *storage));
/* Objects */
-void *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type);
-void **DRW_object_engine_data_ensure(
- Object *ob, DrawEngineType *engine_type, void (*callback)(void *storage));
+ObjectEngineData *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type);
+ObjectEngineData *DRW_object_engine_data_ensure(
+ Object *ob,
+ DrawEngineType *engine_type,
+ size_t size,
+ ObjectEngineDataInitCb init_cb,
+ ObjectEngineDataFreeCb free_cb);
struct LampEngineData *DRW_lamp_engine_data_ensure(Object *ob, struct RenderEngineType *engine_type);
void DRW_lamp_engine_data_free(struct LampEngineData *led);
@@ -417,12 +461,17 @@ void DRW_draw_region_engine_info(void);
void DRW_state_reset_ex(DRWState state);
void DRW_state_reset(void);
+void DRW_state_lock(DRWState state);
void DRW_state_invert_facing(void);
-void DRW_state_clip_planes_add(float plane_eq[4]);
+void DRW_state_clip_planes_count_set(unsigned int plane_ct);
void DRW_state_clip_planes_reset(void);
+/* Culling, return true if object is inside view frustum. */
+bool DRW_culling_sphere_test(BoundSphere *bsphere);
+bool DRW_culling_box_test(BoundBox *bbox);
+
/* Selection */
void DRW_select_load_id(unsigned int id);
@@ -433,6 +482,7 @@ bool DRW_state_is_select(void);
bool DRW_state_is_depth(void);
bool DRW_state_is_image_render(void);
bool DRW_state_is_scene_render(void);
+bool DRW_state_is_opengl_render(void);
bool DRW_state_show_text(void);
bool DRW_state_draw_support(void);
bool DRW_state_draw_background(void);
@@ -443,6 +493,7 @@ struct DRWTextStore *DRW_state_text_cache_get(void);
/* Avoid too many lookups while drawing */
typedef struct DRWContextState {
+
struct ARegion *ar; /* 'CTX_wm_region(C)' */
struct RegionView3D *rv3d; /* 'CTX_wm_region_view3d(C)' */
struct View3D *v3d; /* 'CTX_wm_view3d(C)' */
@@ -450,16 +501,26 @@ typedef struct DRWContextState {
struct Scene *scene; /* 'CTX_data_scene(C)' */
struct ViewLayer *view_layer; /* 'CTX_data_view_layer(C)' */
- /* Use 'scene->obedit' for edit-mode */
+ /* Use 'object_edit' for edit-mode */
struct Object *obact; /* 'OBACT' */
struct RenderEngineType *engine_type;
+ EvaluationContext eval_ctx;
struct Depsgraph *depsgraph;
+ eObjectMode object_mode;
+
/* Last resort (some functions take this as an arg so we can't easily avoid).
* May be NULL when used for selection or depth buffer. */
const struct bContext *evil_C;
+
+ /* ---- */
+
+ /* Cache: initialized by 'drw_context_state_init'. */
+ struct Object *object_pose;
+ struct Object *object_edit;
+
} DRWContextState;
const DRWContextState *DRW_context_state_get(void);
diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c
index 09fe3d68651..c14fe70e0c3 100644
--- a/source/blender/draw/intern/draw_armature.c
+++ b/source/blender/draw/intern/draw_armature.c
@@ -1308,7 +1308,9 @@ static void draw_armature_pose(Object *ob, const float const_color[4])
// if (!(base->flag & OB_FROMDUPLI)) // TODO
{
- if (ob->mode & OB_MODE_POSE) {
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
+ if ((draw_ctx->object_mode & OB_MODE_POSE) || (ob == draw_ctx->object_pose)) {
arm->flag |= ARM_POSEMODE;
}
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 5faf397cc37..06fb71b7e67 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -32,6 +32,8 @@
#include "DNA_modifier_types.h"
#include "DNA_lattice_types.h"
+#include "UI_resources.h"
+
#include "BLI_utildefines.h"
#include "BLI_math.h"
@@ -43,8 +45,10 @@
/* Batch's only (free'd as an array) */
static struct DRWShapeCache {
Gwn_Batch *drw_single_vertice;
+ Gwn_Batch *drw_cursor;
Gwn_Batch *drw_fullscreen_quad;
Gwn_Batch *drw_quad;
+ Gwn_Batch *drw_sphere;
Gwn_Batch *drw_screenspace_circle;
Gwn_Batch *drw_plain_axes;
Gwn_Batch *drw_single_arrow;
@@ -266,7 +270,6 @@ Gwn_Batch *DRW_cache_fullscreen_quad_get(void)
Gwn_Batch *DRW_cache_quad_get(void)
{
if (!SHC.drw_quad) {
- /* Use a triangle instead of a real quad */
float pos[4][2] = {{-1.0f, -1.0f}, { 1.0f, -1.0f}, {1.0f, 1.0f}, {-1.0f, 1.0f}};
float uvs[4][2] = {{ 0.0f, 0.0f}, { 1.0f, 0.0f}, {1.0f, 1.0f}, { 0.0f, 1.0f}};
@@ -294,7 +297,10 @@ Gwn_Batch *DRW_cache_quad_get(void)
/* Sphere */
Gwn_Batch *DRW_cache_sphere_get(void)
{
- return GPU_batch_preset_sphere(2);
+ if (!SHC.drw_sphere) {
+ SHC.drw_sphere = gpu_batch_sphere(32, 24);
+ }
+ return SHC.drw_sphere;
}
/** \} */
@@ -1068,7 +1074,7 @@ Gwn_Batch *DRW_cache_lamp_sunrays_get(void)
if (!SHC.drw_lamp_sunrays) {
float v[2], v1[2], v2[2];
- /* Position Only 3D format */
+ /* Position Only 2D format */
static Gwn_VertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attrib_ct == 0) {
@@ -1076,17 +1082,21 @@ Gwn_Batch *DRW_cache_lamp_sunrays_get(void)
}
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 16);
+ GWN_vertbuf_data_alloc(vbo, 32);
for (int a = 0; a < 8; a++) {
v[0] = sinf((2.0f * M_PI * a) / 8.0f);
v[1] = cosf((2.0f * M_PI * a) / 8.0f);
- mul_v2_v2fl(v1, v, 1.2f);
- mul_v2_v2fl(v2, v, 2.5f);
+ mul_v2_v2fl(v1, v, 1.6f);
+ mul_v2_v2fl(v2, v, 1.9f);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 4, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 1, v2);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 2, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 2 + 1, v2);
+ mul_v2_v2fl(v1, v, 2.2f);
+ mul_v2_v2fl(v2, v, 2.5f);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 2, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 3, v2);
}
SHC.drw_lamp_sunrays = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
@@ -2594,9 +2604,9 @@ Gwn_Batch *DRW_cache_particles_get_hair(ParticleSystem *psys, ModifierData *md)
return DRW_particles_batch_cache_get_hair(psys, md);
}
-Gwn_Batch *DRW_cache_particles_get_dots(ParticleSystem *psys)
+Gwn_Batch *DRW_cache_particles_get_dots(Object *object, ParticleSystem *psys)
{
- return DRW_particles_batch_cache_get_dots(psys);
+ return DRW_particles_batch_cache_get_dots(object, psys);
}
Gwn_Batch *DRW_cache_particles_get_prim(int type)
@@ -2763,3 +2773,91 @@ Gwn_Batch *DRW_cache_hair_get_guide_curve_edges(struct HairSystem *hsys, struct
{
return DRW_hair_batch_cache_get_guide_curve_edges(hsys, scalp, subdiv);
}
+
+/* 3D cursor */
+Gwn_Batch *DRW_cache_cursor_get(void)
+{
+ if (!SHC.drw_cursor) {
+ const float f5 = 0.25f;
+ const float f10 = 0.5f;
+ const float f20 = 1.0f;
+
+ const int segments = 16;
+ const int vert_ct = segments + 8;
+ const int index_ct = vert_ct + 5;
+
+ unsigned char red[3] = {255, 0, 0};
+ unsigned char white[3] = {255, 255, 255};
+ unsigned char crosshair_color[3];
+ UI_GetThemeColor3ubv(TH_VIEW_OVERLAY, crosshair_color);
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, color; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.color = GWN_vertformat_attr_add(&format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ }
+
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init_ex(&elb, GWN_PRIM_LINE_STRIP, index_ct, vert_ct, true);
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, vert_ct);
+
+ int v = 0;
+ for (int i = 0; i < segments; ++i) {
+ float angle = (float)(2 * M_PI) * ((float)i / (float)segments);
+ float x = f10 * cosf(angle);
+ float y = f10 * sinf(angle);
+
+ if (i % 2 == 0)
+ GWN_vertbuf_attr_set(vbo, attr_id.color, v, red);
+ else
+ GWN_vertbuf_attr_set(vbo, attr_id.color, v, white);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){x, y});
+ GWN_indexbuf_add_generic_vert(&elb, v++);
+ }
+ GWN_indexbuf_add_generic_vert(&elb, 0);
+ GWN_indexbuf_add_primitive_restart(&elb);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){-f20, 0});
+ GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
+ GWN_indexbuf_add_generic_vert(&elb, v++);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){-f5, 0});
+ GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
+ GWN_indexbuf_add_generic_vert(&elb, v++);
+
+ GWN_indexbuf_add_primitive_restart(&elb);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){+f5, 0});
+ GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
+ GWN_indexbuf_add_generic_vert(&elb, v++);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){+f20, 0});
+ GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
+ GWN_indexbuf_add_generic_vert(&elb, v++);
+
+ GWN_indexbuf_add_primitive_restart(&elb);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){0, -f20});
+ GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
+ GWN_indexbuf_add_generic_vert(&elb, v++);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){0, -f5});
+ GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
+ GWN_indexbuf_add_generic_vert(&elb, v++);
+
+ GWN_indexbuf_add_primitive_restart(&elb);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){0, +f5});
+ GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
+ GWN_indexbuf_add_generic_vert(&elb, v++);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){0, +f20});
+ GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
+ GWN_indexbuf_add_generic_vert(&elb, v++);
+
+ Gwn_IndexBuf *ibo = GWN_indexbuf_build(&elb);
+
+ SHC.drw_cursor = GWN_batch_create_ex(GWN_PRIM_LINE_STRIP, vbo, ibo, GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
+ }
+ return SHC.drw_cursor;
+} \ No newline at end of file
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 10539af5a94..bae59ff3604 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -37,6 +37,9 @@ struct DerivedMesh;
void DRW_shape_cache_free(void);
+/* 3D cursor */
+struct Gwn_Batch *DRW_cache_cursor_get(void);
+
/* Common Shapes */
struct Gwn_Batch *DRW_cache_fullscreen_quad_get(void);
struct Gwn_Batch *DRW_cache_quad_get(void);
@@ -171,7 +174,7 @@ struct Gwn_Batch *DRW_cache_groom_vert_overlay_get(struct Object *ob, int mode);
/* Particles */
struct Gwn_Batch *DRW_cache_particles_get_hair(struct ParticleSystem *psys, struct ModifierData *md);
-struct Gwn_Batch *DRW_cache_particles_get_dots(struct ParticleSystem *psys);
+struct Gwn_Batch *DRW_cache_particles_get_dots(struct Object *object, struct ParticleSystem *psys);
struct Gwn_Batch *DRW_cache_particles_get_prim(int type);
/* Hair */
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index 21393a2a609..0ac2f11849a 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -137,7 +137,7 @@ void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me);
/* Particles */
struct Gwn_Batch *DRW_particles_batch_cache_get_hair(struct ParticleSystem *psys, struct ModifierData *md);
-struct Gwn_Batch *DRW_particles_batch_cache_get_dots(struct ParticleSystem *psys);
+struct Gwn_Batch *DRW_particles_batch_cache_get_dots(struct Object *object, struct ParticleSystem *psys);
/* Hair */
struct Gwn_Batch *DRW_hair_batch_cache_get_fibers(struct HairSystem *hsys, struct DerivedMesh *scalp, int subdiv,
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index b44c5b8a20b..f7a82c6d0c5 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -1665,6 +1665,46 @@ void DRW_mesh_batch_cache_dirty(Mesh *me, int mode)
}
}
+/**
+ * This only clear the batches associated to the given vertex buffer.
+ **/
+static void mesh_batch_cache_clear_selective(Mesh *me, Gwn_VertBuf *vert)
+{
+ MeshBatchCache *cache = me->batch_cache;
+ if (!cache) {
+ return;
+ }
+
+ BLI_assert(vert != NULL);
+
+ if (cache->pos_with_normals == vert) {
+ GWN_BATCH_DISCARD_SAFE(cache->triangles_with_normals);
+ GWN_BATCH_DISCARD_SAFE(cache->triangles_with_weights);
+ GWN_BATCH_DISCARD_SAFE(cache->triangles_with_vert_colors);
+ GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_id);
+ GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_mask);
+ GWN_BATCH_DISCARD_SAFE(cache->points_with_normals);
+ if (cache->shaded_triangles) {
+ for (int i = 0; i < cache->mat_len; ++i) {
+ GWN_BATCH_DISCARD_SAFE(cache->shaded_triangles[i]);
+ }
+ }
+ MEM_SAFE_FREE(cache->shaded_triangles);
+ if (cache->texpaint_triangles) {
+ for (int i = 0; i < cache->mat_len; ++i) {
+ GWN_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]);
+ }
+ }
+ MEM_SAFE_FREE(cache->texpaint_triangles);
+ GWN_BATCH_DISCARD_SAFE(cache->texpaint_triangles_single);
+ }
+ /* TODO: add the other ones if needed. */
+ else {
+ /* Does not match any vertbuf in the batch cache! */
+ BLI_assert(0);
+ }
+}
+
static void mesh_batch_cache_clear(Mesh *me)
{
MeshBatchCache *cache = me->batch_cache;
@@ -3878,21 +3918,10 @@ void DRW_mesh_cache_sculpt_coords_ensure(Mesh *me)
if (me->batch_cache) {
MeshBatchCache *cache = mesh_batch_cache_get(me);
if (cache && cache->pos_with_normals && cache->is_sculpt_points_tag) {
-
- const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY;
- MeshRenderData *rdata = mesh_render_data_create(me, datatype);
-
- Gwn_VertBuf *pos_with_normals = cache->pos_with_normals;
- cache->pos_with_normals = NULL;
- GWN_vertbuf_clear(pos_with_normals);
- Gwn_VertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
- *pos_with_normals = *vbo;
- GWN_vertformat_copy(&pos_with_normals->format, &vbo->format);
-
- free(vbo);
- cache->pos_with_normals = pos_with_normals;
-
- mesh_render_data_free(rdata);
+ /* XXX Force update of all the batches that contains the pos_with_normals buffer.
+ * TODO(fclem): Ideally, Gawain should provide a way to update a buffer without destroying it. */
+ mesh_batch_cache_clear_selective(me, cache->pos_with_normals);
+ GWN_VERTBUF_DISCARD_SAFE(cache->pos_with_normals);
}
cache->is_sculpt_points_tag = false;
}
diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c
index da0cc457b99..0530d05c199 100644
--- a/source/blender/draw/intern/draw_cache_impl_particles.c
+++ b/source/blender/draw/intern/draw_cache_impl_particles.c
@@ -29,6 +29,8 @@
* \brief Particle API for render engines
*/
+#include "DRW_render.h"
+
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
@@ -53,11 +55,11 @@ static void particle_batch_cache_clear(ParticleSystem *psys);
typedef struct ParticleBatchCache {
Gwn_VertBuf *pos;
- Gwn_IndexBuf *segments;
+ Gwn_IndexBuf *indices;
Gwn_Batch *hairs;
- int segment_count;
+ int elems_count;
int point_count;
/* settings to determine if cache is invalid */
@@ -132,7 +134,7 @@ static void particle_batch_cache_clear(ParticleSystem *psys)
GWN_BATCH_DISCARD_SAFE(cache->hairs);
GWN_VERTBUF_DISCARD_SAFE(cache->pos);
- GWN_INDEXBUF_DISCARD_SAFE(cache->segments);
+ GWN_INDEXBUF_DISCARD_SAFE(cache->indices);
}
void DRW_particle_batch_cache_free(ParticleSystem *psys)
@@ -143,8 +145,8 @@ void DRW_particle_batch_cache_free(ParticleSystem *psys)
static void ensure_seg_pt_count(ParticleSystem *psys, ParticleBatchCache *cache)
{
- if (cache->pos == NULL || cache->segments == NULL) {
- cache->segment_count = 0;
+ if (cache->pos == NULL || cache->indices == NULL) {
+ cache->elems_count = 0;
cache->point_count = 0;
if (psys->pathcache && (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) {
@@ -152,7 +154,7 @@ static void ensure_seg_pt_count(ParticleSystem *psys, ParticleBatchCache *cache)
ParticleCacheKey *path = psys->pathcache[i];
if (path->segments > 0) {
- cache->segment_count += path->segments;
+ cache->elems_count += path->segments + 2;
cache->point_count += path->segments + 1;
}
}
@@ -165,7 +167,7 @@ static void ensure_seg_pt_count(ParticleSystem *psys, ParticleBatchCache *cache)
ParticleCacheKey *path = psys->childcache[i];
if (path->segments > 0) {
- cache->segment_count += path->segments;
+ cache->elems_count += path->segments + 2;
cache->point_count += path->segments + 1;
}
}
@@ -176,128 +178,114 @@ static void ensure_seg_pt_count(ParticleSystem *psys, ParticleBatchCache *cache)
/* Gwn_Batch cache usage. */
static void particle_batch_cache_ensure_pos_and_seg(ParticleSystem *psys, ModifierData *md, ParticleBatchCache *cache)
{
- if (cache->pos == NULL || cache->segments == NULL) {
- int curr_point = 0;
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
-
- GWN_VERTBUF_DISCARD_SAFE(cache->pos);
- GWN_INDEXBUF_DISCARD_SAFE(cache->segments);
-
- static Gwn_VertFormat format = { 0 };
- static struct { uint pos, tan, ind; } attr_id;
- unsigned int *uv_id = NULL;
- int uv_layers = 0;
- MTFace **mtfaces = NULL;
- float (**parent_uvs)[2] = NULL;
- bool simple = psys->part->childtype == PART_CHILD_PARTICLES;
-
- if (psmd) {
- if (CustomData_has_layer(&psmd->dm_final->loopData, CD_MLOOPUV)) {
- uv_layers = CustomData_number_of_layers(&psmd->dm_final->loopData, CD_MLOOPUV);
- }
+ if (cache->pos != NULL && cache->indices != NULL) {
+ return;
+ }
+
+ int curr_point = 0;
+ ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
+
+ GWN_VERTBUF_DISCARD_SAFE(cache->pos);
+ GWN_INDEXBUF_DISCARD_SAFE(cache->indices);
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, tan, ind; } attr_id;
+ unsigned int *uv_id = NULL;
+ int uv_layers = 0;
+ MTFace **mtfaces = NULL;
+ float (**parent_uvs)[2] = NULL;
+ bool simple = psys->part->childtype == PART_CHILD_PARTICLES;
+
+ if (psmd) {
+ if (CustomData_has_layer(&psmd->dm_final->loopData, CD_MLOOPUV)) {
+ uv_layers = CustomData_number_of_layers(&psmd->dm_final->loopData, CD_MLOOPUV);
}
+ }
- GWN_vertformat_clear(&format);
+ GWN_vertformat_clear(&format);
- /* initialize vertex format */
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.tan = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.ind = GWN_vertformat_attr_add(&format, "ind", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ /* initialize vertex format */
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.tan = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.ind = GWN_vertformat_attr_add(&format, "ind", GWN_COMP_I32, 1, GWN_FETCH_INT);
- if (psmd) {
- uv_id = MEM_mallocN(sizeof(*uv_id) * uv_layers, "UV attrib format");
+ if (psmd) {
+ uv_id = MEM_mallocN(sizeof(*uv_id) * uv_layers, "UV attrib format");
- for (int i = 0; i < uv_layers; i++) {
- const char *name = CustomData_get_layer_name(&psmd->dm_final->loopData, CD_MLOOPUV, i);
- char uuid[32];
+ for (int i = 0; i < uv_layers; i++) {
+ const char *name = CustomData_get_layer_name(&psmd->dm_final->loopData, CD_MLOOPUV, i);
+ char uuid[32];
- BLI_snprintf(uuid, sizeof(uuid), "u%u", BLI_ghashutil_strhash_p(name));
- uv_id[i] = GWN_vertformat_attr_add(&format, uuid, GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- }
+ BLI_snprintf(uuid, sizeof(uuid), "u%u", BLI_ghashutil_strhash_p(name));
+ uv_id[i] = GWN_vertformat_attr_add(&format, uuid, GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
}
+ }
- cache->pos = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(cache->pos, cache->point_count);
+ cache->pos = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(cache->pos, cache->point_count);
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_LINES, cache->segment_count, cache->point_count);
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init_ex(&elb, GWN_PRIM_LINE_STRIP, cache->elems_count, cache->point_count, true);
- if (uv_layers) {
- DM_ensure_tessface(psmd->dm_final);
+ if (uv_layers) {
+ DM_ensure_tessface(psmd->dm_final);
- mtfaces = MEM_mallocN(sizeof(*mtfaces) * uv_layers, "Faces UV layers");
+ mtfaces = MEM_mallocN(sizeof(*mtfaces) * uv_layers, "Faces UV layers");
- for (int i = 0; i < uv_layers; i++) {
- mtfaces[i] = (MTFace *)CustomData_get_layer_n(&psmd->dm_final->faceData, CD_MTFACE, i);
- }
+ for (int i = 0; i < uv_layers; i++) {
+ mtfaces[i] = (MTFace *)CustomData_get_layer_n(&psmd->dm_final->faceData, CD_MTFACE, i);
}
+ }
- if (psys->pathcache && (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) {
- if (simple) {
- parent_uvs = MEM_callocN(sizeof(*parent_uvs) * psys->totpart, "Parent particle UVs");
- }
+ if (psys->pathcache && (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) {
+ if (simple) {
+ parent_uvs = MEM_callocN(sizeof(*parent_uvs) * psys->totpart, "Parent particle UVs");
+ }
- for (int i = 0; i < psys->totpart; i++) {
- ParticleCacheKey *path = psys->pathcache[i];
+ for (int i = 0; i < psys->totpart; i++) {
+ ParticleCacheKey *path = psys->pathcache[i];
- if (path->segments > 0) {
- float tangent[3];
- int from = psmd ? psmd->psys->part->from : 0;
- float (*uv)[2] = NULL;
+ if (path->segments > 0) {
+ float tangent[3];
+ int from = psmd ? psmd->psys->part->from : 0;
+ float (*uv)[2] = NULL;
- if (psmd) {
- uv = MEM_callocN(sizeof(*uv) * uv_layers, "Particle UVs");
+ if (psmd) {
+ uv = MEM_callocN(sizeof(*uv) * uv_layers, "Particle UVs");
- if (simple) {
- parent_uvs[i] = uv;
- }
+ if (simple) {
+ parent_uvs[i] = uv;
}
+ }
- if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- ParticleData *particle = &psys->particles[i];
- int num = particle->num_dmcache;
+ if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ ParticleData *particle = &psys->particles[i];
+ int num = particle->num_dmcache;
- if (num == DMCACHE_NOTFOUND) {
- if (particle->num < psmd->dm_final->getNumTessFaces(psmd->dm_final)) {
- num = particle->num;
- }
- }
-
- if (num != DMCACHE_NOTFOUND) {
- MFace *mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE);
-
- for (int j = 0; j < uv_layers; j++) {
- psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, uv[j]);
- }
+ if (num == DMCACHE_NOTFOUND) {
+ if (particle->num < psmd->dm_final->getNumTessFaces(psmd->dm_final)) {
+ num = particle->num;
}
}
- for (int j = 0; j < path->segments; j++) {
- if (j == 0) {
- sub_v3_v3v3(tangent, path[j + 1].co, path[j].co);
- }
- else {
- sub_v3_v3v3(tangent, path[j + 1].co, path[j - 1].co);
- }
-
- GWN_vertbuf_attr_set(cache->pos, attr_id.pos, curr_point, path[j].co);
- GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent);
- GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &i);
+ if (num != DMCACHE_NOTFOUND) {
+ MFace *mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE);
- if (psmd) {
- for (int k = 0; k < uv_layers; k++) {
- GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point, uv[k]);
- }
+ for (int j = 0; j < uv_layers; j++) {
+ psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, uv[j]);
}
-
- GWN_indexbuf_add_line_verts(&elb, curr_point, curr_point + 1);
-
- curr_point++;
}
+ }
- sub_v3_v3v3(tangent, path[path->segments].co, path[path->segments - 1].co);
+ for (int j = 0; j < path->segments; j++) {
+ if (j == 0) {
+ sub_v3_v3v3(tangent, path[j + 1].co, path[j].co);
+ }
+ else {
+ sub_v3_v3v3(tangent, path[j + 1].co, path[j - 1].co);
+ }
- GWN_vertbuf_attr_set(cache->pos, attr_id.pos, curr_point, path[path->segments].co);
+ GWN_vertbuf_attr_set(cache->pos, attr_id.pos, curr_point, path[j].co);
GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent);
GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &i);
@@ -305,102 +293,105 @@ static void particle_batch_cache_ensure_pos_and_seg(ParticleSystem *psys, Modifi
for (int k = 0; k < uv_layers; k++) {
GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point, uv[k]);
}
-
- if (!simple) {
- MEM_freeN(uv);
- }
}
+ GWN_indexbuf_add_generic_vert(&elb, curr_point);
+
curr_point++;
}
- }
- }
- if (psys->childcache) {
- int child_count = psys->totchild * psys->part->disp / 100;
+ sub_v3_v3v3(tangent, path[path->segments].co, path[path->segments - 1].co);
- if (simple && !parent_uvs) {
- parent_uvs = MEM_callocN(sizeof(*parent_uvs) * psys->totpart, "Parent particle UVs");
- }
+ GWN_vertbuf_attr_set(cache->pos, attr_id.pos, curr_point, path[path->segments].co);
+ GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent);
+ GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &i);
- for (int i = 0, x = psys->totpart; i < child_count; i++, x++) {
- ParticleCacheKey *path = psys->childcache[i];
- float tangent[3];
-
- if (path->segments > 0) {
- int from = psmd ? psmd->psys->part->from : 0;
- float (*uv)[2] = NULL;
+ if (psmd) {
+ for (int k = 0; k < uv_layers; k++) {
+ GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point, uv[k]);
+ }
if (!simple) {
- if (psmd) {
- uv = MEM_callocN(sizeof(*uv) * uv_layers, "Particle UVs");
- }
+ MEM_freeN(uv);
+ }
+ }
- if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- ChildParticle *particle = &psys->child[i];
- int num = particle->num;
+ /* finish the segment and add restart primitive */
+ GWN_indexbuf_add_generic_vert(&elb, curr_point);
+ GWN_indexbuf_add_primitive_restart(&elb);
- if (num != DMCACHE_NOTFOUND) {
- MFace *mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE);
+ curr_point++;
+ }
+ }
+ }
- for (int j = 0; j < uv_layers; j++) {
- psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, uv[j]);
- }
- }
- }
- }
- else if (!parent_uvs[psys->child[i].parent]) {
- if (psmd) {
- parent_uvs[psys->child[i].parent] = MEM_callocN(sizeof(*uv) * uv_layers, "Particle UVs");
- }
+ if (psys->childcache) {
+ int child_count = psys->totchild * psys->part->disp / 100;
- if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- ParticleData *particle = &psys->particles[psys->child[i].parent];
- int num = particle->num_dmcache;
+ if (simple && !parent_uvs) {
+ parent_uvs = MEM_callocN(sizeof(*parent_uvs) * psys->totpart, "Parent particle UVs");
+ }
- if (num == DMCACHE_NOTFOUND) {
- if (particle->num < psmd->dm_final->getNumTessFaces(psmd->dm_final)) {
- num = particle->num;
- }
- }
+ for (int i = 0, x = psys->totpart; i < child_count; i++, x++) {
+ ParticleCacheKey *path = psys->childcache[i];
+ float tangent[3];
- if (num != DMCACHE_NOTFOUND) {
- MFace *mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE);
+ if (path->segments > 0) {
+ int from = psmd ? psmd->psys->part->from : 0;
+ float (*uv)[2] = NULL;
- for (int j = 0; j < uv_layers; j++) {
- psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, parent_uvs[psys->child[i].parent][j]);
- }
- }
- }
+ if (!simple) {
+ if (psmd) {
+ uv = MEM_callocN(sizeof(*uv) * uv_layers, "Particle UVs");
}
- for (int j = 0; j < path->segments; j++) {
- if (j == 0) {
- sub_v3_v3v3(tangent, path[j + 1].co, path[j].co);
- }
- else {
- sub_v3_v3v3(tangent, path[j + 1].co, path[j - 1].co);
+ if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ ChildParticle *particle = &psys->child[i];
+ int num = particle->num;
+
+ if (num != DMCACHE_NOTFOUND) {
+ MFace *mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE);
+
+ for (int j = 0; j < uv_layers; j++) {
+ psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, uv[j]);
+ }
}
+ }
+ }
+ else if (!parent_uvs[psys->child[i].parent]) {
+ if (psmd) {
+ parent_uvs[psys->child[i].parent] = MEM_callocN(sizeof(*uv) * uv_layers, "Particle UVs");
+ }
- GWN_vertbuf_attr_set(cache->pos, attr_id.pos, curr_point, path[j].co);
- GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent);
- GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &x);
+ if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ ParticleData *particle = &psys->particles[psys->child[i].parent];
+ int num = particle->num_dmcache;
- if (psmd) {
- for (int k = 0; k < uv_layers; k++) {
- GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point,
- simple ? parent_uvs[psys->child[i].parent][k] : uv[k]);
+ if (num == DMCACHE_NOTFOUND) {
+ if (particle->num < psmd->dm_final->getNumTessFaces(psmd->dm_final)) {
+ num = particle->num;
}
}
- GWN_indexbuf_add_line_verts(&elb, curr_point, curr_point + 1);
+ if (num != DMCACHE_NOTFOUND) {
+ MFace *mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE);
- curr_point++;
+ for (int j = 0; j < uv_layers; j++) {
+ psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, parent_uvs[psys->child[i].parent][j]);
+ }
+ }
}
+ }
- sub_v3_v3v3(tangent, path[path->segments].co, path[path->segments - 1].co);
+ for (int j = 0; j < path->segments; j++) {
+ if (j == 0) {
+ sub_v3_v3v3(tangent, path[j + 1].co, path[j].co);
+ }
+ else {
+ sub_v3_v3v3(tangent, path[j + 1].co, path[j - 1].co);
+ }
- GWN_vertbuf_attr_set(cache->pos, attr_id.pos, curr_point, path[path->segments].co);
+ GWN_vertbuf_attr_set(cache->pos, attr_id.pos, curr_point, path[j].co);
GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent);
GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &x);
@@ -409,88 +400,129 @@ static void particle_batch_cache_ensure_pos_and_seg(ParticleSystem *psys, Modifi
GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point,
simple ? parent_uvs[psys->child[i].parent][k] : uv[k]);
}
-
- if (!simple) {
- MEM_freeN(uv);
- }
}
+ GWN_indexbuf_add_generic_vert(&elb, curr_point);
+
curr_point++;
}
- }
- }
- if (parent_uvs) {
- for (int i = 0; i < psys->totpart; i++) {
- MEM_SAFE_FREE(parent_uvs[i]);
- }
+ sub_v3_v3v3(tangent, path[path->segments].co, path[path->segments - 1].co);
- MEM_freeN(parent_uvs);
- }
+ GWN_vertbuf_attr_set(cache->pos, attr_id.pos, curr_point, path[path->segments].co);
+ GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent);
+ GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &x);
+
+ if (psmd) {
+ for (int k = 0; k < uv_layers; k++) {
+ GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point,
+ simple ? parent_uvs[psys->child[i].parent][k] : uv[k]);
+ }
+
+ if (!simple) {
+ MEM_freeN(uv);
+ }
+ }
+
+ /* finish the segment and add restart primitive */
+ GWN_indexbuf_add_generic_vert(&elb, curr_point);
+ GWN_indexbuf_add_primitive_restart(&elb);
- if (uv_layers) {
- MEM_freeN(mtfaces);
+ curr_point++;
+ }
}
+ }
- if (psmd) {
- MEM_freeN(uv_id);
+ if (parent_uvs) {
+ for (int i = 0; i < psys->totpart; i++) {
+ MEM_SAFE_FREE(parent_uvs[i]);
}
- cache->segments = GWN_indexbuf_build(&elb);
+ MEM_freeN(parent_uvs);
+ }
+
+ if (uv_layers) {
+ MEM_freeN(mtfaces);
}
+
+ if (psmd) {
+ MEM_freeN(uv_id);
+ }
+
+ cache->indices = GWN_indexbuf_build(&elb);
}
-static void particle_batch_cache_ensure_pos(ParticleSystem *psys, ParticleBatchCache *cache)
+static void particle_batch_cache_ensure_pos(Object *object, ParticleSystem *psys, ParticleBatchCache *cache)
{
- if (cache->pos == NULL) {
- static Gwn_VertFormat format = { 0 };
- static unsigned pos_id, rot_id, val_id;
- int i, curr_point;
- ParticleData *pa;
-
- GWN_VERTBUF_DISCARD_SAFE(cache->pos);
- GWN_INDEXBUF_DISCARD_SAFE(cache->segments);
-
- if (format.attrib_ct == 0) {
- /* initialize vertex format */
- pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- rot_id = GWN_vertformat_attr_add(&format, "rot", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
- val_id = GWN_vertformat_attr_add(&format, "val", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ if (cache->pos != NULL) {
+ return;
+ }
+
+ static Gwn_VertFormat format = { 0 };
+ static unsigned pos_id, rot_id, val_id;
+ int i, curr_point;
+ ParticleData *pa;
+ ParticleKey state;
+ ParticleSimulationData sim = {NULL};
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
+ sim.eval_ctx = &draw_ctx->eval_ctx;
+ sim.scene = draw_ctx->scene;
+ sim.ob = object;
+ sim.psys = psys;
+ sim.psmd = psys_get_modifier(object, psys);
+
+ if (psys->part->phystype == PART_PHYS_KEYED) {
+ if (psys->flag & PSYS_KEYED) {
+ psys_count_keyed_targets(&sim);
+ if (psys->totkeyed == 0)
+ return;
}
+ }
- cache->pos = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(cache->pos, psys->totpart);
-
- for (curr_point = 0, i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) {
- if (pa->state.time >= pa->time && pa->state.time < pa->dietime &&
- !(pa->flag & (PARS_NO_DISP | PARS_UNEXIST)))
- {
- float val;
-
- GWN_vertbuf_attr_set(cache->pos, pos_id, curr_point, pa->state.co);
- GWN_vertbuf_attr_set(cache->pos, rot_id, curr_point, pa->state.rot);
-
- switch (psys->part->draw_col) {
- case PART_DRAW_COL_VEL:
- val = len_v3(pa->state.vel) / psys->part->color_vec_max;
- break;
- case PART_DRAW_COL_ACC:
- val = len_v3v3(pa->state.vel, pa->prev_state.vel) / ((pa->state.time - pa->prev_state.time) * psys->part->color_vec_max);
- break;
- default:
- val = -1.0f;
- break;
- }
+ GWN_VERTBUF_DISCARD_SAFE(cache->pos);
+ GWN_INDEXBUF_DISCARD_SAFE(cache->indices);
- GWN_vertbuf_attr_set(cache->pos, val_id, curr_point, &val);
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ rot_id = GWN_vertformat_attr_add(&format, "rot", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ val_id = GWN_vertformat_attr_add(&format, "val", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ }
- curr_point++;
- }
+ cache->pos = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(cache->pos, psys->totpart);
+
+ for (curr_point = 0, i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) {
+ state.time = draw_ctx->eval_ctx.ctime;
+ if (!psys_get_particle_state(&sim, curr_point, &state, 0)) {
+ continue;
}
- if (curr_point != psys->totpart) {
- GWN_vertbuf_data_resize(cache->pos, curr_point);
+ float val;
+
+ GWN_vertbuf_attr_set(cache->pos, pos_id, curr_point, pa->state.co);
+ GWN_vertbuf_attr_set(cache->pos, rot_id, curr_point, pa->state.rot);
+
+ switch (psys->part->draw_col) {
+ case PART_DRAW_COL_VEL:
+ val = len_v3(pa->state.vel) / psys->part->color_vec_max;
+ break;
+ case PART_DRAW_COL_ACC:
+ val = len_v3v3(pa->state.vel, pa->prev_state.vel) / ((pa->state.time - pa->prev_state.time) * psys->part->color_vec_max);
+ break;
+ default:
+ val = -1.0f;
+ break;
}
+
+ GWN_vertbuf_attr_set(cache->pos, val_id, curr_point, &val);
+
+ curr_point++;
+ }
+
+ if (curr_point != psys->totpart) {
+ GWN_vertbuf_data_resize(cache->pos, curr_point);
}
}
@@ -501,18 +533,18 @@ Gwn_Batch *DRW_particles_batch_cache_get_hair(ParticleSystem *psys, ModifierData
if (cache->hairs == NULL) {
ensure_seg_pt_count(psys, cache);
particle_batch_cache_ensure_pos_and_seg(psys, md, cache);
- cache->hairs = GWN_batch_create(GWN_PRIM_LINES, cache->pos, cache->segments);
+ cache->hairs = GWN_batch_create(GWN_PRIM_LINE_STRIP, cache->pos, cache->indices);
}
return cache->hairs;
}
-Gwn_Batch *DRW_particles_batch_cache_get_dots(ParticleSystem *psys)
+Gwn_Batch *DRW_particles_batch_cache_get_dots(Object *object, ParticleSystem *psys)
{
ParticleBatchCache *cache = particle_batch_cache_get(psys);
if (cache->hairs == NULL) {
- particle_batch_cache_ensure_pos(psys, cache);
+ particle_batch_cache_ensure_pos(object, psys, cache);
cache->hairs = GWN_batch_create(GWN_PRIM_POINTS, cache->pos, NULL);
}
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index 0eb97a54ba5..8d23688959c 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -35,7 +35,6 @@
#include "draw_common.h"
-
#if 0
#define UI_COLOR_RGB_FROM_U8(r, g, b, v4) \
ARRAY_SET_ITEMS(v4, (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, 1.0)
@@ -123,12 +122,12 @@ void DRW_globals_update(void)
ts.sizeEdge = 1.0f / 2.0f; /* TODO Theme */
ts.sizeEdgeFix = 0.5f + 2.0f * (2.0f * (MAX2(ts.sizeVertex, ts.sizeEdge)) * (float)M_SQRT1_2);
- /* TODO Waiting for notifiers to invalidate cache */
- if (globals_ubo) {
- DRW_uniformbuffer_free(globals_ubo);
+
+ if (globals_ubo == NULL) {
+ globals_ubo = DRW_uniformbuffer_create(sizeof(GlobalsUboStorage), &ts);
}
- globals_ubo = DRW_uniformbuffer_create(sizeof(GlobalsUboStorage), &ts);
+ DRW_uniformbuffer_update(globals_ubo, &ts);
ColorBand ramp = {0};
float *colors;
@@ -157,6 +156,29 @@ void DRW_globals_update(void)
/* ********************************* SHGROUP ************************************* */
+static struct {
+ struct Gwn_VertFormat *instance_screenspace;
+ struct Gwn_VertFormat *instance_color;
+ struct Gwn_VertFormat *instance_screen_aligned;
+ struct Gwn_VertFormat *instance_scaled;
+ struct Gwn_VertFormat *instance_sized;
+ struct Gwn_VertFormat *instance;
+ struct Gwn_VertFormat *instance_camera;
+ struct Gwn_VertFormat *instance_distance_lines;
+ struct Gwn_VertFormat *instance_spot;
+ struct Gwn_VertFormat *instance_bone_envelope_wire;
+ struct Gwn_VertFormat *instance_bone_envelope_solid;
+ struct Gwn_VertFormat *instance_mball_handles;
+} g_formats = {NULL};
+
+void DRW_globals_free(void)
+{
+ struct Gwn_VertFormat **format = &g_formats.instance_screenspace;
+ for (int i = 0; i < sizeof(g_formats) / sizeof(void *); ++i, ++format) {
+ MEM_SAFE_FREE(*format);
+ }
+}
+
DRWShadingGroup *shgroup_dynlines_uniform_color(DRWPass *pass, float color[4])
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
@@ -204,9 +226,12 @@ DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Gwn_Batch *g
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
- DRW_shgroup_attrib_float(grp, "world_pos", 3);
- DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_instance_format(g_formats.instance_screenspace, {
+ {"world_pos", DRW_ATTRIB_FLOAT, 3},
+ {"color" , DRW_ATTRIB_FLOAT, 3}
+ });
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_screenspace);
DRW_shgroup_uniform_float(grp, "size", size, 1);
DRW_shgroup_uniform_float(grp, "pixel_size", DRW_viewport_pixelsize_get(), 1);
DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
@@ -220,9 +245,12 @@ DRWShadingGroup *shgroup_instance_solid(DRWPass *pass, struct Gwn_Batch *geom)
static float light[3] = {0.0f, 0.0f, 1.0f};
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
- DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
- DRW_shgroup_attrib_float(grp, "color", 4);
+ DRW_shgroup_instance_format(g_formats.instance_color, {
+ {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16},
+ {"color" , DRW_ATTRIB_FLOAT, 4}
+ });
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_color);
DRW_shgroup_uniform_vec3(grp, "light", light, 1);
return grp;
@@ -232,9 +260,12 @@ DRWShadingGroup *shgroup_instance_wire(DRWPass *pass, struct Gwn_Batch *geom)
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
- DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
- DRW_shgroup_attrib_float(grp, "color", 4);
+ DRW_shgroup_instance_format(g_formats.instance_color, {
+ {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16},
+ {"color" , DRW_ATTRIB_FLOAT, 4}
+ });
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_color);
return grp;
}
@@ -243,10 +274,13 @@ DRWShadingGroup *shgroup_instance_screen_aligned(DRWPass *pass, struct Gwn_Batch
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED);
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
- DRW_shgroup_attrib_float(grp, "color", 3);
- DRW_shgroup_attrib_float(grp, "size", 1);
- DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_instance_format(g_formats.instance_screen_aligned, {
+ {"color" , DRW_ATTRIB_FLOAT, 3},
+ {"size" , DRW_ATTRIB_FLOAT, 1},
+ {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}
+ });
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_screen_aligned);
DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
return grp;
@@ -256,10 +290,13 @@ DRWShadingGroup *shgroup_instance_axis_names(DRWPass *pass, struct Gwn_Batch *ge
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS);
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
- DRW_shgroup_attrib_float(grp, "color", 3);
- DRW_shgroup_attrib_float(grp, "size", 1);
- DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_instance_format(g_formats.instance_screen_aligned, {
+ {"color" , DRW_ATTRIB_FLOAT, 3},
+ {"size" , DRW_ATTRIB_FLOAT, 1},
+ {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}
+ });
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_screen_aligned);
DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
return grp;
@@ -269,10 +306,13 @@ DRWShadingGroup *shgroup_instance_scaled(DRWPass *pass, struct Gwn_Batch *geom)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE);
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
- DRW_shgroup_attrib_float(grp, "color", 3);
- DRW_shgroup_attrib_float(grp, "size", 3);
- DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_instance_format(g_formats.instance_scaled, {
+ {"color" , DRW_ATTRIB_FLOAT, 3},
+ {"size" , DRW_ATTRIB_FLOAT, 3},
+ {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}
+ });
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_scaled);
return grp;
}
@@ -281,10 +321,13 @@ DRWShadingGroup *shgroup_instance(DRWPass *pass, struct Gwn_Batch *geom)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE);
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
- DRW_shgroup_attrib_float(grp, "color", 3);
- DRW_shgroup_attrib_float(grp, "size", 1);
- DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_instance_format(g_formats.instance_sized, {
+ {"color" , DRW_ATTRIB_FLOAT, 3},
+ {"size" , DRW_ATTRIB_FLOAT, 1},
+ {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}
+ });
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_sized);
return grp;
}
@@ -293,12 +336,15 @@ DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, struct Gwn_Batch *geom)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_CAMERA);
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
- DRW_shgroup_attrib_float(grp, "color", 3);
- DRW_shgroup_attrib_float(grp, "corners", 8);
- DRW_shgroup_attrib_float(grp, "depth", 1);
- DRW_shgroup_attrib_float(grp, "tria", 4);
- DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_instance_format(g_formats.instance_camera, {
+ {"color" , DRW_ATTRIB_FLOAT, 3},
+ {"corners" , DRW_ATTRIB_FLOAT, 8},
+ {"depth" , DRW_ATTRIB_FLOAT, 1},
+ {"tria" , DRW_ATTRIB_FLOAT, 4},
+ {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}
+ });
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_camera);
return grp;
}
@@ -308,11 +354,14 @@ DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct Gwn_Batch
GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_DISTANCE_LINES);
static float point_size = 4.0f;
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
- DRW_shgroup_attrib_float(grp, "color", 3);
- DRW_shgroup_attrib_float(grp, "start", 1);
- DRW_shgroup_attrib_float(grp, "end", 1);
- DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_instance_format(g_formats.instance_distance_lines, {
+ {"color" , DRW_ATTRIB_FLOAT, 3},
+ {"start" , DRW_ATTRIB_FLOAT, 1},
+ {"end" , DRW_ATTRIB_FLOAT, 1},
+ {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}
+ });
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_distance_lines);
DRW_shgroup_uniform_float(grp, "size", &point_size, 1);
return grp;
@@ -324,9 +373,12 @@ DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Gwn_Batch *geom)
static const int True = true;
static const int False = false;
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
- DRW_shgroup_attrib_float(grp, "color", 3);
- DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_instance_format(g_formats.instance_spot, {
+ {"color" , DRW_ATTRIB_FLOAT, 3},
+ {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}
+ });
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_spot);
DRW_shgroup_uniform_bool(grp, "drawFront", &False, 1);
DRW_shgroup_uniform_bool(grp, "drawBack", &False, 1);
DRW_shgroup_uniform_bool(grp, "drawSilhouette", &True, 1);
@@ -338,12 +390,15 @@ DRWShadingGroup *shgroup_instance_bone_envelope_wire(DRWPass *pass, struct Gwn_B
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_WIRE);
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
- DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
- DRW_shgroup_attrib_float(grp, "color", 4);
- DRW_shgroup_attrib_float(grp, "radius_head", 1);
- DRW_shgroup_attrib_float(grp, "radius_tail", 1);
- DRW_shgroup_attrib_float(grp, "distance", 1);
+ DRW_shgroup_instance_format(g_formats.instance_bone_envelope_wire, {
+ {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16},
+ {"color" , DRW_ATTRIB_FLOAT, 4},
+ {"radius_head" , DRW_ATTRIB_FLOAT, 1},
+ {"radius_tail" , DRW_ATTRIB_FLOAT, 1},
+ {"distance" , DRW_ATTRIB_FLOAT, 1}
+ });
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_bone_envelope_wire);
return grp;
}
@@ -353,24 +408,30 @@ DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass, struct Gwn_
static float light[3] = {0.0f, 0.0f, 1.0f};
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID);
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
- DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
- DRW_shgroup_attrib_float(grp, "color", 4);
- DRW_shgroup_attrib_float(grp, "radius_head", 1);
- DRW_shgroup_attrib_float(grp, "radius_tail", 1);
+ DRW_shgroup_instance_format(g_formats.instance_bone_envelope_solid, {
+ {"InstanceModelMatrix" , DRW_ATTRIB_FLOAT, 16},
+ {"color" , DRW_ATTRIB_FLOAT, 4},
+ {"radius_head" , DRW_ATTRIB_FLOAT, 1},
+ {"radius_tail" , DRW_ATTRIB_FLOAT, 1}
+ });
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_bone_envelope_solid);
DRW_shgroup_uniform_vec3(grp, "light", light, 1);
return grp;
}
-DRWShadingGroup *shgroup_instance_mball_helpers(DRWPass *pass, struct Gwn_Batch *geom)
+DRWShadingGroup *shgroup_instance_mball_handles(DRWPass *pass, struct Gwn_Batch *geom)
{
- GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_MBALL_HELPERS);
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_MBALL_HANDLES);
+
+ DRW_shgroup_instance_format(g_formats.instance_mball_handles, {
+ {"ScaleTranslationMatrix" , DRW_ATTRIB_FLOAT, 12},
+ {"radius" , DRW_ATTRIB_FLOAT, 1},
+ {"color" , DRW_ATTRIB_FLOAT, 3}
+ });
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
- DRW_shgroup_attrib_float(grp, "ScaleTranslationMatrix", 12);
- DRW_shgroup_attrib_float(grp, "radius", 1);
- DRW_shgroup_attrib_float(grp, "color", 3);
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_mball_handles);
DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
return grp;
@@ -386,7 +447,8 @@ DRWShadingGroup *shgroup_instance_mball_helpers(DRWPass *pass, struct Gwn_Batch
*/
int DRW_object_wire_theme_get(Object *ob, ViewLayer *view_layer, float **r_color)
{
- const bool is_edit = (ob->mode & OB_MODE_EDIT) != 0;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const bool is_edit = (draw_ctx->object_mode & OB_MODE_EDIT) != 0;
const bool active = (view_layer->basact && view_layer->basact->object == ob);
/* confusing logic here, there are 2 methods of setting the color
* 'colortab[colindex]' and 'theme_id', colindex overrides theme_id.
@@ -419,6 +481,7 @@ int DRW_object_wire_theme_get(Object *ob, ViewLayer *view_layer, float **r_color
else if (ob->type == OB_SPEAKER) theme_id = TH_SPEAKER;
else if (ob->type == OB_CAMERA) theme_id = TH_CAMERA;
else if (ob->type == OB_EMPTY) theme_id = TH_EMPTY;
+ else if (ob->type == OB_LIGHTPROBE) theme_id = TH_EMPTY; /* TODO add lightprobe color */
/* fallback to TH_WIRE */
}
}
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index 93e63308fb6..3d498cba8b6 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -105,6 +105,7 @@ typedef struct GlobalsUboStorage {
/* Keep in sync with globalsBlock in shaders */
void DRW_globals_update(void);
+void DRW_globals_free(void);
struct DRWShadingGroup *shgroup_dynlines_uniform_color(struct DRWPass *pass, float color[4]);
struct DRWShadingGroup *shgroup_dynpoints_uniform_color(struct DRWPass *pass, float color[4], float *size);
@@ -123,9 +124,10 @@ struct DRWShadingGroup *shgroup_distance_lines_instance(struct DRWPass *pass, st
struct DRWShadingGroup *shgroup_spot_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_bone_envelope_wire(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_bone_envelope_solid(struct DRWPass *pass, struct Gwn_Batch *geom);
-struct DRWShadingGroup *shgroup_instance_mball_helpers(struct DRWPass *pass, struct Gwn_Batch *geom);
+struct DRWShadingGroup *shgroup_instance_mball_handles(struct DRWPass *pass, struct Gwn_Batch *geom);
-int DRW_object_wire_theme_get(struct Object *ob, struct ViewLayer *view_layer, float **r_color);
+int DRW_object_wire_theme_get(
+ struct Object *ob, struct ViewLayer *view_layer, float **r_color);
float *DRW_color_background_blend_get(int theme_id);
/* draw_armature.c */
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index 82a2143e72a..8f61c46479c 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -55,7 +55,7 @@ void DRW_hair_shader_uniforms(DRWShadingGroup *shgrp, Scene *UNUSED(scene),
static float test = 2.5f;
DRW_shgroup_uniform_float(shgrp, "ribbon_width", &test, 1);
- DRW_shgroup_uniform_buffer(shgrp, "fiber_data", fibertex);
+ DRW_shgroup_uniform_texture_ref(shgrp, "fiber_data", fibertex);
DRW_shgroup_uniform_int(shgrp, "strand_map_start", &texbuffer->strand_map_start, 1);
DRW_shgroup_uniform_int(shgrp, "strand_vertex_start", &texbuffer->strand_vertex_start, 1);
DRW_shgroup_uniform_int(shgrp, "fiber_start", &texbuffer->fiber_start, 1);
diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c
index e7ce4374d1c..ee73a2ba2c6 100644
--- a/source/blender/draw/intern/draw_instance_data.c
+++ b/source/blender/draw/intern/draw_instance_data.c
@@ -34,11 +34,37 @@
#include "draw_instance_data.h"
#include "DRW_engine.h"
+#include "DRW_render.h" /* For DRW_shgroup_get_instance_count() */
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
-#define MAX_INSTANCE_DATA_SIZE 32 /* Can be adjusted for more */
+#define BUFFER_CHUNK_SIZE 32
+#define BUFFER_VERTS_CHUNK 32
+
+typedef struct DRWBatchingBuffer {
+ struct DRWShadingGroup *shgroup; /* Link back to the owning shGroup. Also tells if it's used */
+ Gwn_VertFormat *format; /* Identifier. */
+ Gwn_VertBuf *vert; /* Gwn_VertBuf contained in the Gwn_Batch. */
+ Gwn_Batch *batch; /* Gwn_Batch containing the Gwn_VertBuf. */
+} DRWBatchingBuffer;
+
+typedef struct DRWInstancingBuffer {
+ struct DRWShadingGroup *shgroup; /* Link back to the owning shGroup. Also tells if it's used */
+ Gwn_VertFormat *format; /* Identifier. */
+ Gwn_Batch *instance; /* Identifier. */
+ Gwn_VertBuf *vert; /* Gwn_VertBuf contained in the Gwn_Batch. */
+ Gwn_Batch *batch; /* Gwn_Batch containing the Gwn_VertBuf. */
+} DRWInstancingBuffer;
+
+typedef struct DRWInstanceChunk {
+ size_t cursor; /* Offset to the next instance data. */
+ size_t alloc_size; /* Number of DRWBatchingBuffer/Batches alloc'd in ibufs/btchs. */
+ union {
+ DRWBatchingBuffer *bbufs;
+ DRWInstancingBuffer *ibufs;
+ };
+} DRWInstanceChunk;
struct DRWInstanceData {
struct DRWInstanceData *next;
@@ -51,13 +77,206 @@ struct DRWInstanceData {
};
struct DRWInstanceDataList {
+ struct DRWInstanceDataList *next, *prev;
/* Linked lists for all possible data pool size */
/* Not entirely sure if we should separate them in the first place.
* This is done to minimize the reattribution misses. */
DRWInstanceData *idata_head[MAX_INSTANCE_DATA_SIZE];
DRWInstanceData *idata_tail[MAX_INSTANCE_DATA_SIZE];
+
+ DRWInstanceChunk instancing;
+ DRWInstanceChunk batching;
};
+static ListBase g_idatalists = {NULL, NULL};
+
+/* -------------------------------------------------------------------- */
+
+/** \name Instance Buffer Management
+ * \{ */
+
+/**
+ * This manager allows to distribute existing batches for instancing
+ * attributes. This reduce the number of batches creation.
+ * Querying a batch is done with a vertex format. This format should
+ * be static so that it's pointer never changes (because we are using
+ * this pointer as identifier [we don't want to check the full format
+ * that would be too slow]).
+ **/
+
+static void instance_batch_free(Gwn_Batch *batch, void *UNUSED(user_data))
+{
+ /* Free all batches that have the same key before they are reused. */
+ /* TODO: Make it thread safe! Batch freeing can happen from another thread. */
+ /* XXX we need to iterate over all idatalists unless we make some smart
+ * data structure to store the locations to update. */
+ for (DRWInstanceDataList *idatalist = g_idatalists.first; idatalist; idatalist = idatalist->next) {
+ DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs;
+ for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) {
+ if (ibuf->instance == batch) {
+ BLI_assert(ibuf->shgroup == NULL); /* Make sure it has no other users. */
+ GWN_VERTBUF_DISCARD_SAFE(ibuf->vert);
+ GWN_BATCH_DISCARD_SAFE(ibuf->batch);
+ /* Tag as non alloced. */
+ ibuf->format = NULL;
+ }
+ }
+ }
+}
+
+void DRW_batching_buffer_request(
+ DRWInstanceDataList *idatalist, Gwn_VertFormat *format, Gwn_PrimType type, struct DRWShadingGroup *shgroup,
+ Gwn_Batch **r_batch, Gwn_VertBuf **r_vert)
+{
+ DRWInstanceChunk *chunk = &idatalist->batching;
+ DRWBatchingBuffer *bbuf = idatalist->batching.bbufs;
+ BLI_assert(format);
+ /* Search for an unused batch. */
+ for (int i = 0; i < idatalist->batching.alloc_size; i++, bbuf++) {
+ if (bbuf->shgroup == NULL) {
+ if (bbuf->format == format) {
+ bbuf->shgroup = shgroup;
+ *r_batch = bbuf->batch;
+ *r_vert = bbuf->vert;
+ return;
+ }
+ }
+ }
+ int new_id = 0; /* Find insertion point. */
+ for (; new_id < chunk->alloc_size; ++new_id) {
+ if (chunk->bbufs[new_id].format == NULL)
+ break;
+ }
+ /* If there is no batch left. Allocate more. */
+ if (new_id == chunk->alloc_size) {
+ new_id = chunk->alloc_size;
+ chunk->alloc_size += BUFFER_CHUNK_SIZE;
+ chunk->bbufs = MEM_reallocN(chunk->bbufs, chunk->alloc_size * sizeof(DRWBatchingBuffer));
+ memset(chunk->bbufs + new_id, 0, sizeof(DRWBatchingBuffer) * BUFFER_CHUNK_SIZE);
+ }
+ /* Create the batch. */
+ bbuf = chunk->bbufs + new_id;
+ bbuf->vert = *r_vert = GWN_vertbuf_create_with_format_ex(format, GWN_USAGE_DYNAMIC);
+ bbuf->batch = *r_batch = GWN_batch_create_ex(type, bbuf->vert, NULL, 0);
+ bbuf->format = format;
+ bbuf->shgroup = shgroup;
+ GWN_vertbuf_data_alloc(*r_vert, BUFFER_VERTS_CHUNK);
+}
+
+void DRW_instancing_buffer_request(
+ DRWInstanceDataList *idatalist, Gwn_VertFormat *format, Gwn_Batch *instance, struct DRWShadingGroup *shgroup,
+ Gwn_Batch **r_batch, Gwn_VertBuf **r_vert)
+{
+ DRWInstanceChunk *chunk = &idatalist->instancing;
+ DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs;
+ BLI_assert(format);
+ /* Search for an unused batch. */
+ for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) {
+ if (ibuf->shgroup == NULL) {
+ if (ibuf->format == format) {
+ if (ibuf->instance == instance) {
+ ibuf->shgroup = shgroup;
+ *r_batch = ibuf->batch;
+ *r_vert = ibuf->vert;
+ return;
+ }
+ }
+ }
+ }
+ int new_id = 0; /* Find insertion point. */
+ for (; new_id < chunk->alloc_size; ++new_id) {
+ if (chunk->ibufs[new_id].format == NULL)
+ break;
+ }
+ /* If there is no batch left. Allocate more. */
+ if (new_id == chunk->alloc_size) {
+ new_id = chunk->alloc_size;
+ chunk->alloc_size += BUFFER_CHUNK_SIZE;
+ chunk->ibufs = MEM_reallocN(chunk->ibufs, chunk->alloc_size * sizeof(DRWInstancingBuffer));
+ memset(chunk->ibufs + new_id, 0, sizeof(DRWInstancingBuffer) * BUFFER_CHUNK_SIZE);
+ }
+ /* Create the batch. */
+ ibuf = chunk->ibufs + new_id;
+ ibuf->vert = *r_vert = GWN_vertbuf_create_with_format_ex(format, GWN_USAGE_DYNAMIC);
+ ibuf->batch = *r_batch = GWN_batch_duplicate(instance);
+ ibuf->format = format;
+ ibuf->shgroup = shgroup;
+ ibuf->instance = instance;
+ GWN_vertbuf_data_alloc(*r_vert, BUFFER_VERTS_CHUNK);
+ GWN_batch_instbuf_set(ibuf->batch, ibuf->vert, false);
+ /* Make sure to free this ibuf if the instance batch gets free. */
+ GWN_batch_callback_free_set(instance, &instance_batch_free, NULL);
+}
+
+void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist)
+{
+ size_t realloc_size = 1; /* Avoid 0 size realloc. */
+ /* Resize down buffers in use and send data to GPU & free unused buffers. */
+ DRWInstanceChunk *batching = &idatalist->batching;
+ DRWBatchingBuffer *bbuf = batching->bbufs;
+ for (int i = 0; i < batching->alloc_size; i++, bbuf++) {
+ if (bbuf->shgroup != NULL) {
+ realloc_size = i + 1;
+ unsigned int vert_ct = DRW_shgroup_get_instance_count(bbuf->shgroup);
+ vert_ct += (vert_ct == 0) ? 1 : 0; /* Do not realloc to 0 size buffer */
+ if (vert_ct + BUFFER_VERTS_CHUNK <= bbuf->vert->vertex_ct) {
+ unsigned int size = vert_ct + BUFFER_VERTS_CHUNK - 1;
+ size = size - size % BUFFER_VERTS_CHUNK;
+ GWN_vertbuf_data_resize(bbuf->vert, size);
+ }
+ GWN_vertbuf_use(bbuf->vert); /* Send data. */
+ bbuf->shgroup = NULL; /* Set as non used for the next round. */
+ }
+ else {
+ GWN_VERTBUF_DISCARD_SAFE(bbuf->vert);
+ GWN_BATCH_DISCARD_SAFE(bbuf->batch);
+ bbuf->format = NULL; /* Tag as non alloced. */
+ }
+ }
+ /* Rounding up to nearest chunk size. */
+ realloc_size += BUFFER_CHUNK_SIZE - 1;
+ realloc_size -= realloc_size % BUFFER_CHUNK_SIZE;
+ /* Resize down if necessary. */
+ if (realloc_size < batching->alloc_size) {
+ batching->alloc_size = realloc_size;
+ batching->ibufs = MEM_reallocN(batching->ibufs, realloc_size * sizeof(DRWBatchingBuffer));
+ }
+
+ realloc_size = 1;
+ /* Resize down buffers in use and send data to GPU & free unused buffers. */
+ DRWInstanceChunk *instancing = &idatalist->instancing;
+ DRWInstancingBuffer *ibuf = instancing->ibufs;
+ for (int i = 0; i < instancing->alloc_size; i++, ibuf++) {
+ if (ibuf->shgroup != NULL) {
+ realloc_size = i + 1;
+ unsigned int vert_ct = DRW_shgroup_get_instance_count(ibuf->shgroup);
+ vert_ct += (vert_ct == 0) ? 1 : 0; /* Do not realloc to 0 size buffer */
+ if (vert_ct + BUFFER_VERTS_CHUNK <= ibuf->vert->vertex_ct) {
+ unsigned int size = vert_ct + BUFFER_VERTS_CHUNK - 1;
+ size = size - size % BUFFER_VERTS_CHUNK;
+ GWN_vertbuf_data_resize(ibuf->vert, size);
+ }
+ GWN_vertbuf_use(ibuf->vert); /* Send data. */
+ ibuf->shgroup = NULL; /* Set as non used for the next round. */
+ }
+ else {
+ GWN_VERTBUF_DISCARD_SAFE(ibuf->vert);
+ GWN_BATCH_DISCARD_SAFE(ibuf->batch);
+ ibuf->format = NULL; /* Tag as non alloced. */
+ }
+ }
+ /* Rounding up to nearest chunk size. */
+ realloc_size += BUFFER_CHUNK_SIZE - 1;
+ realloc_size -= realloc_size % BUFFER_CHUNK_SIZE;
+ /* Resize down if necessary. */
+ if (realloc_size < instancing->alloc_size) {
+ instancing->alloc_size = realloc_size;
+ instancing->ibufs = MEM_reallocN(instancing->ibufs, realloc_size * sizeof(DRWInstancingBuffer));
+ }
+}
+
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name Instance Data (DRWInstanceData)
@@ -66,7 +285,7 @@ struct DRWInstanceDataList {
static DRWInstanceData *drw_instance_data_create(
DRWInstanceDataList *idatalist, unsigned int attrib_size, unsigned int instance_group)
{
- DRWInstanceData *idata = MEM_mallocN(sizeof(DRWInstanceData), "DRWInstanceData");
+ DRWInstanceData *idata = MEM_callocN(sizeof(DRWInstanceData), "DRWInstanceData");
idata->next = NULL;
idata->used = true;
idata->data_size = attrib_size;
@@ -145,7 +364,15 @@ DRWInstanceData *DRW_instance_data_request(
DRWInstanceDataList *DRW_instance_data_list_create(void)
{
- return MEM_callocN(sizeof(DRWInstanceDataList), "DRWInstanceDataList");
+ DRWInstanceDataList *idatalist = MEM_callocN(sizeof(DRWInstanceDataList), "DRWInstanceDataList");
+ idatalist->batching.bbufs = MEM_callocN(sizeof(DRWBatchingBuffer) * BUFFER_CHUNK_SIZE, "DRWBatchingBuffers");
+ idatalist->batching.alloc_size = BUFFER_CHUNK_SIZE;
+ idatalist->instancing.ibufs = MEM_callocN(sizeof(DRWInstancingBuffer) * BUFFER_CHUNK_SIZE, "DRWInstancingBuffers");
+ idatalist->instancing.alloc_size = BUFFER_CHUNK_SIZE;
+
+ BLI_addtail(&g_idatalists, idatalist);
+
+ return idatalist;
}
void DRW_instance_data_list_free(DRWInstanceDataList *idatalist)
@@ -161,6 +388,22 @@ void DRW_instance_data_list_free(DRWInstanceDataList *idatalist)
idatalist->idata_head[i] = NULL;
idatalist->idata_tail[i] = NULL;
}
+
+ DRWBatchingBuffer *bbuf = idatalist->batching.bbufs;
+ for (int i = 0; i < idatalist->batching.alloc_size; i++, bbuf++) {
+ GWN_VERTBUF_DISCARD_SAFE(bbuf->vert);
+ GWN_BATCH_DISCARD_SAFE(bbuf->batch);
+ }
+ MEM_freeN(idatalist->batching.bbufs);
+
+ DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs;
+ for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) {
+ GWN_VERTBUF_DISCARD_SAFE(ibuf->vert);
+ GWN_BATCH_DISCARD_SAFE(ibuf->batch);
+ }
+ MEM_freeN(idatalist->instancing.ibufs);
+
+ BLI_remlink(&g_idatalists, idatalist);
}
void DRW_instance_data_list_reset(DRWInstanceDataList *idatalist)
diff --git a/source/blender/draw/intern/draw_instance_data.h b/source/blender/draw/intern/draw_instance_data.h
index 637c0e3cc24..3b0f7839277 100644
--- a/source/blender/draw/intern/draw_instance_data.h
+++ b/source/blender/draw/intern/draw_instance_data.h
@@ -26,14 +26,33 @@
#ifndef __DRAW_INSTANCE_DATA_H__
#define __DRAW_INSTANCE_DATA_H__
+#include "BLI_compiler_attrs.h"
+#include "BLI_sys_types.h"
+
+#include "GPU_batch.h"
+
+#define MAX_INSTANCE_DATA_SIZE 42 /* Can be adjusted for more */
+
typedef struct DRWInstanceData DRWInstanceData;
typedef struct DRWInstanceDataList DRWInstanceDataList;
+struct DRWShadingGroup;
+
void *DRW_instance_data_next(DRWInstanceData *idata);
void *DRW_instance_data_get(DRWInstanceData *idata);
DRWInstanceData *DRW_instance_data_request(
DRWInstanceDataList *idatalist, unsigned int attrib_size, unsigned int instance_group);
+void DRW_batching_buffer_request(
+ DRWInstanceDataList *idatalist, Gwn_VertFormat *format, Gwn_PrimType type, struct DRWShadingGroup *shgroup,
+ Gwn_Batch **r_batch, Gwn_VertBuf **r_vert);
+void DRW_instancing_buffer_request(
+ DRWInstanceDataList *idatalist, Gwn_VertFormat *format, Gwn_Batch *instance, struct DRWShadingGroup *shgroup,
+ Gwn_Batch **r_batch, Gwn_VertBuf **r_vert);
+
+/* Upload all instance data to the GPU as soon as possible. */
+void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist);
+
void DRW_instance_data_list_reset(DRWInstanceDataList *idatalist);
void DRW_instance_data_list_free_unused(DRWInstanceDataList *idatalist);
void DRW_instance_data_list_resize(DRWInstanceDataList *idatalist);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index e5b959cdd3b..752fc52b9b7 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -29,45 +29,28 @@
#include "BLI_mempool.h"
#include "BLI_rect.h"
#include "BLI_string.h"
-#include "BLI_string_utils.h"
+#include "BLI_threads.h"
-#include "BIF_glutil.h"
+#include "BLF_api.h"
-#include "BKE_curve.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
-#include "BKE_pbvh.h"
-#include "BKE_paint.h"
#include "BKE_workspace.h"
-#include "BLT_translation.h"
-#include "BLF_api.h"
-
-#include "DRW_engine.h"
-#include "DRW_render.h"
-
+#include "draw_manager.h"
#include "DNA_camera_types.h"
-#include "DNA_curve_types.h"
-#include "DNA_view3d_types.h"
-#include "DNA_screen_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_meta_types.h"
#include "ED_space_api.h"
#include "ED_screen.h"
+#include "ED_view3d.h"
-#include "intern/gpu_codegen.h"
-#include "GPU_batch.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
-#include "GPU_lamp.h"
-#include "GPU_material.h"
-#include "GPU_shader.h"
-#include "GPU_texture.h"
#include "GPU_uniformbuffer.h"
#include "GPU_viewport.h"
#include "GPU_matrix.h"
@@ -75,12 +58,13 @@
#include "IMB_colormanagement.h"
#include "RE_engine.h"
+#include "RE_pipeline.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "WM_api.h"
-#include "WM_types.h"
+#include "wm_window.h"
#include "draw_manager_text.h"
#include "draw_manager_profiling.h"
@@ -88,2043 +72,45 @@
/* only for callbacks */
#include "draw_cache_impl.h"
-#include "draw_instance_data.h"
-
#include "draw_mode_engines.h"
#include "engines/clay/clay_engine.h"
#include "engines/eevee/eevee_engine.h"
#include "engines/basic/basic_engine.h"
#include "engines/external/external_engine.h"
+#include "../../../intern/gawain/gawain/gwn_context.h"
+
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-/* -------------------------------------------------------------------- */
-/** \name Local Features
- * \{ */
-
-#define USE_PROFILE
-
-#ifdef USE_PROFILE
-# include "PIL_time.h"
-
-# define PROFILE_TIMER_FALLOFF 0.1
-
-# define PROFILE_START(time_start) \
- double time_start = PIL_check_seconds_timer();
-
-# define PROFILE_END_ACCUM(time_accum, time_start) { \
- time_accum += (PIL_check_seconds_timer() - time_start) * 1e3; \
-} ((void)0)
-
-/* exp average */
-# define PROFILE_END_UPDATE(time_update, time_start) { \
- double _time_delta = (PIL_check_seconds_timer() - time_start) * 1e3; \
- time_update = (time_update * (1.0 - PROFILE_TIMER_FALLOFF)) + \
- (_time_delta * PROFILE_TIMER_FALLOFF); \
-} ((void)0)
-
-#else /* USE_PROFILE */
-
-# define PROFILE_START(time_start) ((void)0)
-# define PROFILE_END_ACCUM(time_accum, time_start) ((void)0)
-# define PROFILE_END_UPDATE(time_update, time_start) ((void)0)
-
-#endif /* USE_PROFILE */
-
-
-/* Use draw manager to call GPU_select, see: DRW_draw_select_loop */
-#define USE_GPU_SELECT
-
#ifdef USE_GPU_SELECT
-# include "ED_view3d.h"
-# include "ED_armature.h"
# include "GPU_select.h"
#endif
-/** \} */
-
-
-#define MAX_ATTRIB_NAME 32
-#define MAX_ATTRIB_COUNT 6 /* Can be adjusted for more */
-#define MAX_PASS_NAME 32
-#define MAX_CLIP_PLANES 6 /* GL_MAX_CLIP_PLANES is at least 6 */
-
-extern char datatoc_gpu_shader_2D_vert_glsl[];
-extern char datatoc_gpu_shader_3D_vert_glsl[];
-extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
-
-/* Prototypes. */
-static void drw_engines_enable_external(void);
-
-/* Structures */
-typedef enum {
- DRW_UNIFORM_BOOL,
- DRW_UNIFORM_SHORT_TO_INT,
- DRW_UNIFORM_SHORT_TO_FLOAT,
- DRW_UNIFORM_INT,
- DRW_UNIFORM_FLOAT,
- DRW_UNIFORM_TEXTURE,
- DRW_UNIFORM_BUFFER,
- DRW_UNIFORM_MAT3,
- DRW_UNIFORM_MAT4,
- DRW_UNIFORM_BLOCK
-} DRWUniformType;
-
-typedef enum {
- DRW_ATTRIB_INT,
- DRW_ATTRIB_FLOAT,
-} DRWAttribType;
-
-struct DRWUniform {
- struct DRWUniform *next;
- DRWUniformType type;
- int location;
- int length;
- int arraysize;
- const void *value;
-};
-
-struct DRWInterface {
- DRWUniform *uniforms; /* DRWUniform, single-linked list */
- int attribs_count;
- int attribs_stride;
- int attribs_size[16];
- int attribs_loc[16];
- /* matrices locations */
- int model;
- int modelinverse;
- int modelview;
- int modelviewinverse;
- int projection;
- int projectioninverse;
- int view;
- int viewinverse;
- int modelviewprojection;
- int viewprojection;
- int viewprojectioninverse;
- int normal;
- int worldnormal;
- int camtexfac;
- int orcotexfac;
- int eye;
- int clipplanes;
- /* Dynamic batch */
- Gwn_Batch *instance_batch; /* contains instances attributes */
- GLuint instance_vbo; /* same as instance_batch but generated from DRWCalls */
- struct DRWInstanceData *inst_data;
-#ifdef USE_GPU_SELECT
- struct DRWInstanceData *inst_selectid;
- /* Override for single object instances. */
- int override_selectid;
-#endif
- int instance_count;
- Gwn_VertFormat vbo_format;
-};
-
-struct DRWPass {
- /* Single linked list with last member to append */
- DRWShadingGroup *shgroups;
- DRWShadingGroup *shgroups_last;
-
- DRWState state;
- char name[MAX_PASS_NAME];
-};
-
-typedef struct DRWCallHeader {
- void *prev;
-
-#ifdef USE_GPU_SELECT
- int select_id;
-#endif
- uchar type;
-} DRWCallHeader;
-
-typedef struct DRWCall {
- DRWCallHeader head;
-
- float obmat[4][4];
- Gwn_Batch *geometry;
-
- Object *ob; /* Optional */
- ID *ob_data; /* Optional. */
-} DRWCall;
-
-typedef struct DRWCallGenerate {
- DRWCallHeader head;
-
- float obmat[4][4];
-
- DRWCallGenerateFn *geometry_fn;
- void *user_data;
-} DRWCallGenerate;
-
-struct DRWShadingGroup {
- struct DRWShadingGroup *next;
-
- GPUShader *shader; /* Shader to bind */
- DRWInterface interface; /* Uniforms pointers */
-
- /* DRWCall or DRWCallDynamic depending of type */
- void *calls;
- void *calls_first; /* To be able to traverse the list in the order of addition */
-
- DRWState state_extra; /* State changes for this batch only (or'd with the pass's state) */
- DRWState state_extra_disable; /* State changes for this batch only (and'd with the pass's state) */
- unsigned int stencil_mask; /* Stencil mask to use for stencil test / write operations */
- int type;
-
- ID *instance_data; /* Object->data to instance */
- Gwn_Batch *instance_geom; /* Geometry to instance */
- Gwn_Batch *batch_geom; /* Result of call batching */
-
-#ifdef USE_GPU_SELECT
- /* backlink to pass we're in */
- DRWPass *pass_parent;
-#endif
-};
-
-/* Used by DRWShadingGroup.type */
-enum {
- DRW_SHG_NORMAL,
- DRW_SHG_POINT_BATCH,
- DRW_SHG_LINE_BATCH,
- DRW_SHG_TRIANGLE_BATCH,
- DRW_SHG_INSTANCE,
-};
-
-/* Used by DRWCall.type */
-enum {
- /* A single batch */
- DRW_CALL_SINGLE,
- /* Uses a callback to draw with any number of batches. */
- DRW_CALL_GENERATE,
- /* Arbitrary number of multiple args. */
- DRW_CALL_DYNAMIC,
-};
-
/** Render State: No persistent data between draw calls. */
-static struct DRWGlobalState {
- /* Cache generation */
- ViewportMemoryPool *vmempool;
- DRWUniform *last_uniform;
- DRWCall *last_call;
- DRWCallGenerate *last_callgenerate;
- DRWShadingGroup *last_shgroup;
- DRWInstanceDataList *idatalist;
-
- /* Rendering state */
- GPUShader *shader;
-
- /* Managed by `DRW_state_set`, `DRW_state_reset` */
- DRWState state;
- unsigned int stencil_mask;
-
- /* Per viewport */
- GPUViewport *viewport;
- struct GPUFrameBuffer *default_framebuffer;
- float size[2];
- float screenvecs[2][3];
- float pixsize;
-
- GLenum backface, frontface;
-
- /* Clip planes */
- int num_clip_planes;
- float clip_planes_eq[MAX_CLIP_PLANES][4];
-
- struct {
- unsigned int is_select : 1;
- unsigned int is_depth : 1;
- unsigned int is_image_render : 1;
- unsigned int is_scene_render : 1;
- unsigned int draw_background : 1;
- } options;
-
- /* Current rendering context */
- DRWContextState draw_ctx;
-
- /* Convenience pointer to text_store owned by the viewport */
- struct DRWTextStore **text_store_p;
-
- ListBase enabled_engines; /* RenderEngineType */
-
- /* Profiling */
- double cache_time;
-} DST = {NULL};
-
-/** GPU Resource State: Memory storage between drawing. */
-static struct DRWResourceState {
- GPUTexture **bound_texs;
-
- bool *bound_tex_slots;
-
- int bind_tex_inc;
- int bind_ubo_inc;
-} RST = {NULL};
-
-static struct DRWMatrixOveride {
- float mat[6][4][4];
- bool override[6];
-} viewport_matrix_override = {{{{0}}}};
+DRWManager DST = {NULL};
ListBase DRW_engines = {NULL, NULL};
-#ifdef USE_GPU_SELECT
-static unsigned int g_DRW_select_id = (unsigned int)-1;
-
-void DRW_select_load_id(unsigned int id)
-{
- BLI_assert(G.f & G_PICKSEL);
- g_DRW_select_id = id;
-}
-#endif
-
-
-/* -------------------------------------------------------------------- */
-
-/** \name Textures (DRW_texture)
- * \{ */
-
-static void drw_texture_get_format(
- DRWTextureFormat format,
- GPUTextureFormat *r_data_type, int *r_channels)
-{
- switch (format) {
- case DRW_TEX_RGBA_8: *r_data_type = GPU_RGBA8; break;
- case DRW_TEX_RGBA_16: *r_data_type = GPU_RGBA16F; break;
- case DRW_TEX_RGB_16: *r_data_type = GPU_RGB16F; break;
- case DRW_TEX_RGB_11_11_10: *r_data_type = GPU_R11F_G11F_B10F; break;
- case DRW_TEX_RG_8: *r_data_type = GPU_RG8; break;
- case DRW_TEX_RG_16: *r_data_type = GPU_RG16F; break;
- case DRW_TEX_RG_16I: *r_data_type = GPU_RG16I; break;
- case DRW_TEX_RG_32: *r_data_type = GPU_RG32F; break;
- case DRW_TEX_R_8: *r_data_type = GPU_R8; break;
- case DRW_TEX_R_16: *r_data_type = GPU_R16F; break;
- case DRW_TEX_R_32: *r_data_type = GPU_R32F; break;
-#if 0
- case DRW_TEX_RGBA_32: *r_data_type = GPU_RGBA32F; break;
- case DRW_TEX_RGB_8: *r_data_type = GPU_RGB8; break;
- case DRW_TEX_RGB_32: *r_data_type = GPU_RGB32F; break;
-#endif
- case DRW_TEX_DEPTH_16: *r_data_type = GPU_DEPTH_COMPONENT16; break;
- case DRW_TEX_DEPTH_24: *r_data_type = GPU_DEPTH_COMPONENT24; break;
- case DRW_TEX_DEPTH_24_STENCIL_8: *r_data_type = GPU_DEPTH24_STENCIL8; break;
- case DRW_TEX_DEPTH_32: *r_data_type = GPU_DEPTH_COMPONENT32F; break;
- default :
- /* file type not supported you must uncomment it from above */
- BLI_assert(false);
- break;
- }
-
- switch (format) {
- case DRW_TEX_RGBA_8:
- case DRW_TEX_RGBA_16:
- case DRW_TEX_RGBA_32:
- *r_channels = 4;
- break;
- case DRW_TEX_RGB_8:
- case DRW_TEX_RGB_16:
- case DRW_TEX_RGB_32:
- case DRW_TEX_RGB_11_11_10:
- *r_channels = 3;
- break;
- case DRW_TEX_RG_8:
- case DRW_TEX_RG_16:
- case DRW_TEX_RG_16I:
- case DRW_TEX_RG_32:
- *r_channels = 2;
- break;
- default:
- *r_channels = 1;
- break;
- }
-}
-
-static void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags)
-{
- GPU_texture_bind(tex, 0);
- if (flags & DRW_TEX_MIPMAP) {
- GPU_texture_mipmap_mode(tex, true, flags & DRW_TEX_FILTER);
- DRW_texture_generate_mipmaps(tex);
- }
- else {
- GPU_texture_filter_mode(tex, flags & DRW_TEX_FILTER);
- }
- GPU_texture_wrap_mode(tex, flags & DRW_TEX_WRAP);
- GPU_texture_compare_mode(tex, flags & DRW_TEX_COMPARE);
- GPU_texture_unbind(tex);
-}
-
-GPUTexture *DRW_texture_create_1D(int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels)
-{
- GPUTexture *tex;
- GPUTextureFormat data_type;
- int channels;
-
- drw_texture_get_format(format, &data_type, &channels);
- tex = GPU_texture_create_1D_custom(w, channels, data_type, fpixels, NULL);
- drw_texture_set_parameters(tex, flags);
-
- return tex;
-}
-
-GPUTexture *DRW_texture_create_2D(int w, int h, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels)
-{
- GPUTexture *tex;
- GPUTextureFormat data_type;
- int channels;
-
- drw_texture_get_format(format, &data_type, &channels);
- tex = GPU_texture_create_2D_custom(w, h, channels, data_type, fpixels, NULL);
- drw_texture_set_parameters(tex, flags);
-
- return tex;
-}
-
-GPUTexture *DRW_texture_create_2D_array(
- int w, int h, int d, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels)
-{
- GPUTexture *tex;
- GPUTextureFormat data_type;
- int channels;
-
- drw_texture_get_format(format, &data_type, &channels);
- tex = GPU_texture_create_2D_array_custom(w, h, d, channels, data_type, fpixels, NULL);
- drw_texture_set_parameters(tex, flags);
-
- return tex;
-}
-
-GPUTexture *DRW_texture_create_3D(
- int w, int h, int d, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels)
-{
- GPUTexture *tex;
- GPUTextureFormat data_type;
- int channels;
-
- drw_texture_get_format(format, &data_type, &channels);
- tex = GPU_texture_create_3D_custom(w, h, d, channels, data_type, fpixels, NULL);
- drw_texture_set_parameters(tex, flags);
-
- return tex;
-}
-
-GPUTexture *DRW_texture_create_cube(int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels)
-{
- GPUTexture *tex;
- GPUTextureFormat data_type;
- int channels;
-
- drw_texture_get_format(format, &data_type, &channels);
- tex = GPU_texture_create_cube_custom(w, channels, data_type, fpixels, NULL);
- drw_texture_set_parameters(tex, flags);
-
- return tex;
-}
-
-void DRW_texture_generate_mipmaps(GPUTexture *tex)
-{
- GPU_texture_bind(tex, 0);
- GPU_texture_generate_mipmap(tex);
- GPU_texture_unbind(tex);
-}
-
-void DRW_texture_update(GPUTexture *tex, const float *pixels)
-{
- GPU_texture_update(tex, pixels);
-}
-
-void DRW_texture_free(GPUTexture *tex)
-{
- GPU_texture_free(tex);
-}
-
-/** \} */
-
-
-/* -------------------------------------------------------------------- */
-
-/** \name Uniform Buffer Object (DRW_uniformbuffer)
- * \{ */
-
-GPUUniformBuffer *DRW_uniformbuffer_create(int size, const void *data)
-{
- return GPU_uniformbuffer_create(size, data, NULL);
-}
-
-void DRW_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data)
-{
- GPU_uniformbuffer_update(ubo, data);
-}
-
-void DRW_uniformbuffer_free(GPUUniformBuffer *ubo)
-{
- GPU_uniformbuffer_free(ubo);
-}
-
-/** \} */
-
-
-/* -------------------------------------------------------------------- */
-
-/** \name Shaders (DRW_shader)
- * \{ */
-
-GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *frag, const char *defines)
-{
- return GPU_shader_create(vert, frag, geom, NULL, defines);
-}
-
-GPUShader *DRW_shader_create_with_lib(
- const char *vert, const char *geom, const char *frag, const char *lib, const char *defines)
-{
- GPUShader *sh;
- char *vert_with_lib = NULL;
- char *frag_with_lib = NULL;
- char *geom_with_lib = NULL;
-
- vert_with_lib = BLI_string_joinN(lib, vert);
- frag_with_lib = BLI_string_joinN(lib, frag);
-
- if (geom) {
- geom_with_lib = BLI_string_joinN(lib, geom);
- }
-
- sh = GPU_shader_create(vert_with_lib, frag_with_lib, geom_with_lib, NULL, defines);
-
- MEM_freeN(vert_with_lib);
- MEM_freeN(frag_with_lib);
- if (geom) {
- MEM_freeN(geom_with_lib);
- }
-
- return sh;
-}
-
-GPUShader *DRW_shader_create_2D(const char *frag, const char *defines)
-{
- return GPU_shader_create(datatoc_gpu_shader_2D_vert_glsl, frag, NULL, NULL, defines);
-}
-
-GPUShader *DRW_shader_create_3D(const char *frag, const char *defines)
-{
- return GPU_shader_create(datatoc_gpu_shader_3D_vert_glsl, frag, NULL, NULL, defines);
-}
-
-GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines)
-{
- return GPU_shader_create(datatoc_gpu_shader_fullscreen_vert_glsl, frag, NULL, NULL, defines);
-}
-
-GPUShader *DRW_shader_create_3D_depth_only(void)
-{
- return GPU_shader_get_builtin_shader(GPU_SHADER_3D_DEPTH_ONLY);
-}
-
-void DRW_shader_free(GPUShader *shader)
-{
- GPU_shader_free(shader);
-}
-
-/** \} */
-
-
-/* -------------------------------------------------------------------- */
-
-/** \name Interface (DRW_interface)
- * \{ */
-
-static void drw_interface_create(DRWInterface *interface, GPUShader *shader)
-{
- interface->model = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODEL);
- interface->modelinverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODEL_INV);
- interface->modelview = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODELVIEW);
- interface->modelviewinverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODELVIEW_INV);
- interface->projection = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_PROJECTION);
- interface->projectioninverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_PROJECTION_INV);
- interface->view = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_VIEW);
- interface->viewinverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_VIEW_INV);
- interface->viewprojection = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_VIEWPROJECTION);
- interface->viewprojectioninverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_VIEWPROJECTION_INV);
- interface->modelviewprojection = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MVP);
- interface->normal = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_NORMAL);
- interface->worldnormal = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_WORLDNORMAL);
- interface->camtexfac = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_CAMERATEXCO);
- interface->orcotexfac = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_ORCO);
- interface->clipplanes = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_CLIPPLANES);
- interface->eye = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_EYE);
- interface->instance_count = 0;
- interface->attribs_count = 0;
- interface->attribs_stride = 0;
- interface->instance_vbo = 0;
- interface->instance_batch = NULL;
- interface->inst_data = NULL;
- interface->uniforms = NULL;
-#ifdef USE_GPU_SELECT
- interface->inst_selectid = NULL;
- interface->override_selectid = -1;
-#endif
-
- memset(&interface->vbo_format, 0, sizeof(Gwn_VertFormat));
-}
-
-
-static void drw_interface_uniform(DRWShadingGroup *shgroup, const char *name,
- DRWUniformType type, const void *value, int length, int arraysize)
-{
- int location;
- if (type == DRW_UNIFORM_BLOCK) {
- location = GPU_shader_get_uniform_block(shgroup->shader, name);
- }
- else {
- location = GPU_shader_get_uniform(shgroup->shader, name);
- }
-
- if (location == -1) {
- if (G.debug & G_DEBUG)
- fprintf(stderr, "Uniform '%s' not found!\n", name);
- /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */
- // BLI_assert(0);
- return;
- }
-
- DRWUniform *uni = BLI_mempool_alloc(DST.vmempool->uniforms);
-
- BLI_assert(arraysize > 0);
-
- uni->location = location;
- uni->type = type;
- uni->value = value;
- uni->length = length;
- uni->arraysize = arraysize;
-
- /* Prepend */
- uni->next = shgroup->interface.uniforms;
- shgroup->interface.uniforms = uni;
-}
-
-static void drw_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRWAttribType UNUSED(type), int size, bool dummy)
-{
- unsigned int attrib_id = shgroup->interface.attribs_count;
- GLuint program = GPU_shader_get_program(shgroup->shader);
-
- shgroup->interface.attribs_loc[attrib_id] = glGetAttribLocation(program, name);
- shgroup->interface.attribs_size[attrib_id] = size;
- shgroup->interface.attribs_stride += size;
- shgroup->interface.attribs_count += 1;
-
- if (shgroup->type != DRW_SHG_INSTANCE) {
- BLI_assert(size <= 4); /* Matrices are not supported by Gawain. */
- GWN_vertformat_attr_add(&shgroup->interface.vbo_format, name, GWN_COMP_F32, size, GWN_FETCH_FLOAT);
- }
-
- BLI_assert(shgroup->interface.attribs_count < MAX_ATTRIB_COUNT);
-
-/* Adding attribute even if not found for now (to keep memory alignment).
- * Should ideally take vertex format automatically from batch eventually */
-#if 0
- if (attrib->location == -1 && !dummy) {
- if (G.debug & G_DEBUG)
- fprintf(stderr, "Attribute '%s' not found!\n", name);
- BLI_assert(0);
- MEM_freeN(attrib);
- return;
- }
-#else
- UNUSED_VARS(dummy);
-#endif
-}
-
-/** \} */
-
-
-/* -------------------------------------------------------------------- */
-
-/** \name Shading Group (DRW_shgroup)
- * \{ */
-
-DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
-{
- DRWShadingGroup *shgroup = BLI_mempool_alloc(DST.vmempool->shgroups);
-
- /* Append */
- if (pass->shgroups != NULL) {
- pass->shgroups_last->next = shgroup;
- }
- else {
- pass->shgroups = shgroup;
- }
- pass->shgroups_last = shgroup;
- shgroup->next = NULL;
-
- drw_interface_create(&shgroup->interface, shader);
-
- shgroup->type = DRW_SHG_NORMAL;
- shgroup->shader = shader;
- shgroup->state_extra = 0;
- shgroup->state_extra_disable = ~0x0;
- shgroup->stencil_mask = 0;
- shgroup->batch_geom = NULL;
- shgroup->instance_geom = NULL;
- shgroup->instance_data = NULL;
-
- shgroup->calls = NULL;
- shgroup->calls_first = NULL;
-
-#ifdef USE_GPU_SELECT
- shgroup->pass_parent = pass;
-#endif
-
- return shgroup;
-}
-
-DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPass *pass)
-{
- double time = 0.0; /* TODO make time variable */
-
- /* TODO : Ideally we should not convert. But since the whole codegen
- * is relying on GPUPass we keep it as is for now. */
- GPUPass *gpupass = GPU_material_get_pass(material);
-
- if (!gpupass) {
- /* Shader compilation error */
- return NULL;
- }
-
- struct GPUShader *shader = GPU_pass_shader(gpupass);
-
- DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
-
- /* Converting dynamic GPUInput to DRWUniform */
- ListBase *inputs = &gpupass->inputs;
-
- for (GPUInput *input = inputs->first; input; input = input->next) {
- /* Textures */
- if (input->ima) {
- GPUTexture *tex = GPU_texture_from_blender(
- input->ima, input->iuser, input->textarget, input->image_isdata, time, 1);
-
- if (input->bindtex) {
- DRW_shgroup_uniform_texture(grp, input->shadername, tex);
- }
- }
- /* Color Ramps */
- else if (input->tex) {
- DRW_shgroup_uniform_texture(grp, input->shadername, input->tex);
- }
- /* Floats */
- else {
- switch (input->type) {
- case GPU_FLOAT:
- case GPU_VEC2:
- case GPU_VEC3:
- case GPU_VEC4:
- /* Should already be in the material ubo. */
- break;
- case GPU_MAT3:
- DRW_shgroup_uniform_mat3(grp, input->shadername, (float *)input->dynamicvec);
- break;
- case GPU_MAT4:
- DRW_shgroup_uniform_mat4(grp, input->shadername, (float *)input->dynamicvec);
- break;
- default:
- break;
- }
- }
- }
-
- GPUUniformBuffer *ubo = GPU_material_get_uniform_buffer(material);
- if (ubo != NULL) {
- DRW_shgroup_uniform_block(grp, GPU_UBO_BLOCK_NAME, ubo);
- }
-
- return grp;
-}
-
-DRWShadingGroup *DRW_shgroup_material_instance_create(
- struct GPUMaterial *material, DRWPass *pass, Gwn_Batch *geom, Object *ob)
-{
- DRWShadingGroup *shgroup = DRW_shgroup_material_create(material, pass);
-
- if (shgroup) {
- shgroup->type = DRW_SHG_INSTANCE;
- shgroup->instance_geom = geom;
- shgroup->instance_data = ob->data;
- }
-
- return shgroup;
-}
-
-DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(
- struct GPUMaterial *material, DRWPass *pass, int size)
-{
- DRWShadingGroup *shgroup = DRW_shgroup_material_create(material, pass);
-
- if (shgroup) {
- shgroup->type = DRW_SHG_TRIANGLE_BATCH;
- shgroup->interface.instance_count = size * 3;
- drw_interface_attrib(shgroup, "dummy", DRW_ATTRIB_FLOAT, 1, true);
- }
-
- return shgroup;
-}
-
-DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader, DRWPass *pass, Gwn_Batch *geom)
-{
- DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass);
-
- shgroup->type = DRW_SHG_INSTANCE;
- shgroup->instance_geom = geom;
-
- return shgroup;
-}
-
-DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass)
-{
- DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass);
-
- shgroup->type = DRW_SHG_POINT_BATCH;
- DRW_shgroup_attrib_float(shgroup, "pos", 3);
-
- return shgroup;
-}
-
-DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass)
-{
- DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass);
-
- shgroup->type = DRW_SHG_LINE_BATCH;
- DRW_shgroup_attrib_float(shgroup, "pos", 3);
-
- return shgroup;
-}
-
-/* Very special batch. Use this if you position
- * your vertices with the vertex shader
- * and dont need any VBO attrib */
-DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DRWPass *pass, int size)
-{
- DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass);
-
- shgroup->type = DRW_SHG_TRIANGLE_BATCH;
- shgroup->interface.instance_count = size * 3;
- drw_interface_attrib(shgroup, "dummy", DRW_ATTRIB_FLOAT, 1, true);
-
- return shgroup;
-}
-
-void DRW_shgroup_free(struct DRWShadingGroup *shgroup)
-{
- if (shgroup->interface.instance_vbo &&
- (shgroup->interface.instance_batch == 0))
- {
- glDeleteBuffers(1, &shgroup->interface.instance_vbo);
- }
-
- GWN_BATCH_DISCARD_SAFE(shgroup->batch_geom);
-}
-
-#define CALL_PREPEND(shgroup, call) { \
- if (shgroup->calls == NULL) { \
- shgroup->calls = call; \
- shgroup->calls_first = call; \
- } \
- else { \
- ((DRWCall *)(shgroup->calls))->head.prev = call; \
- shgroup->calls = call; \
- } \
- call->head.prev = NULL; \
-} ((void)0)
-
-void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *instances)
-{
- BLI_assert(shgroup->type == DRW_SHG_INSTANCE);
- BLI_assert(shgroup->interface.instance_batch == NULL);
-
- shgroup->interface.instance_batch = instances;
-
-#ifdef USE_GPU_SELECT
- DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
- call->head.select_id = g_DRW_select_id;
-
- CALL_PREPEND(shgroup, call);
-#endif
-}
-
-void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4])
-{
- BLI_assert(geom != NULL);
- BLI_assert(shgroup->type == DRW_SHG_NORMAL);
-
- DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
-
- CALL_PREPEND(shgroup, call);
-
- call->head.type = DRW_CALL_SINGLE;
-#ifdef USE_GPU_SELECT
- call->head.select_id = g_DRW_select_id;
-#endif
-
- if (obmat != NULL) {
- copy_m4_m4(call->obmat, obmat);
- }
-
- call->geometry = geom;
- call->ob_data = NULL;
-}
+extern struct GPUUniformBuffer *view_ubo; /* draw_manager_exec.c */
-void DRW_shgroup_call_object_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob)
+static void drw_state_prepare_clean_for_draw(DRWManager *dst)
{
- BLI_assert(geom != NULL);
- BLI_assert(shgroup->type == DRW_SHG_NORMAL);
-
- DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
-
- CALL_PREPEND(shgroup, call);
-
- call->head.type = DRW_CALL_SINGLE;
-#ifdef USE_GPU_SELECT
- call->head.select_id = g_DRW_select_id;
-#endif
-
- copy_m4_m4(call->obmat, ob->obmat);
- call->geometry = geom;
- call->ob_data = ob->data;
-}
-
-void DRW_shgroup_call_generate_add(
- DRWShadingGroup *shgroup,
- DRWCallGenerateFn *geometry_fn, void *user_data,
- float (*obmat)[4])
-{
- BLI_assert(geometry_fn != NULL);
- BLI_assert(shgroup->type == DRW_SHG_NORMAL);
-
- DRWCallGenerate *call = BLI_mempool_alloc(DST.vmempool->calls_generate);
-
- CALL_PREPEND(shgroup, call);
-
- call->head.type = DRW_CALL_GENERATE;
-#ifdef USE_GPU_SELECT
- call->head.select_id = g_DRW_select_id;
-#endif
-
- if (obmat != NULL) {
- copy_m4_m4(call->obmat, obmat);
- }
-
- call->geometry_fn = geometry_fn;
- call->user_data = user_data;
+ memset(dst, 0x0, offsetof(DRWManager, ogl_context));
}
-static void sculpt_draw_cb(
- DRWShadingGroup *shgroup,
- void (*draw_fn)(DRWShadingGroup *shgroup, Gwn_Batch *geom),
- void *user_data)
-{
- Object *ob = user_data;
- PBVH *pbvh = ob->sculpt->pbvh;
-
- if (pbvh) {
- BKE_pbvh_draw_cb(
- pbvh, NULL, NULL, false,
- (void (*)(void *, Gwn_Batch *))draw_fn, shgroup);
- }
-}
-
-void DRW_shgroup_call_sculpt_add(DRWShadingGroup *shgroup, Object *ob, float (*obmat)[4])
-{
- DRW_shgroup_call_generate_add(shgroup, sculpt_draw_cb, ob, obmat);
-}
-
-void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *attr[], unsigned int attr_len)
-{
- DRWInterface *interface = &shgroup->interface;
-
-#ifdef USE_GPU_SELECT
- if (G.f & G_PICKSEL) {
- if (interface->inst_selectid == NULL) {
- interface->inst_selectid = DRW_instance_data_request(DST.idatalist, 1, 128);
- }
-
- int *select_id = DRW_instance_data_next(interface->inst_selectid);
- *select_id = g_DRW_select_id;
- }
-#endif
-
- BLI_assert(attr_len == interface->attribs_count);
- UNUSED_VARS_NDEBUG(attr_len);
-
- if (interface->attribs_stride > 0) {
- if (interface->inst_data == NULL) {
- interface->inst_data = DRW_instance_data_request(DST.idatalist, interface->attribs_stride, 16);
- }
-
- float *data = DRW_instance_data_next(interface->inst_data);
-
- for (int i = 0; i < interface->attribs_count; ++i) {
- memcpy(data, attr[i], sizeof(float) * interface->attribs_size[i]);
- data = data + interface->attribs_size[i];
- }
- }
-
- interface->instance_count += 1;
-}
-
-/* Used for instancing with no attributes */
-void DRW_shgroup_set_instance_count(DRWShadingGroup *shgroup, int count)
-{
- DRWInterface *interface = &shgroup->interface;
-
- BLI_assert(interface->instance_count == 0);
- BLI_assert(interface->attribs_count == 0);
-
-#ifdef USE_GPU_SELECT
- if (G.f & G_PICKSEL) {
- interface->override_selectid = g_DRW_select_id;
- }
-#endif
-
- interface->instance_count = count;
-}
-
-/**
- * State is added to #Pass.state while drawing.
- * Use to temporarily enable draw options.
+/* This function is used to reset draw manager to a state
+ * where we don't re-use data by accident across different
+ * draw calls.
*/
-void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state)
-{
- shgroup->state_extra |= state;
-}
-
-void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state)
-{
- shgroup->state_extra_disable &= ~state;
-}
-
-void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, unsigned int mask)
-{
- shgroup->stencil_mask = mask;
-}
-
-void DRW_shgroup_attrib_float(DRWShadingGroup *shgroup, const char *name, int size)
-{
- drw_interface_attrib(shgroup, name, DRW_ATTRIB_FLOAT, size, false);
-}
-
-void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
-{
- drw_interface_uniform(shgroup, name, DRW_UNIFORM_TEXTURE, tex, 0, 1);
-}
-
-void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const GPUUniformBuffer *ubo)
-{
- drw_interface_uniform(shgroup, name, DRW_UNIFORM_BLOCK, ubo, 0, 1);
-}
-
-void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
-{
- drw_interface_uniform(shgroup, name, DRW_UNIFORM_BUFFER, tex, 0, 1);
-}
-
-void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
-{
- drw_interface_uniform(shgroup, name, DRW_UNIFORM_BOOL, value, 1, arraysize);
-}
-
-void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
-{
- drw_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 1, arraysize);
-}
-
-void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
-{
- drw_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 2, arraysize);
-}
-
-void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
-{
- drw_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 3, arraysize);
-}
-
-void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
-{
- drw_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 4, arraysize);
-}
-
-void DRW_shgroup_uniform_short_to_int(DRWShadingGroup *shgroup, const char *name, const short *value, int arraysize)
-{
- drw_interface_uniform(shgroup, name, DRW_UNIFORM_SHORT_TO_INT, value, 1, arraysize);
-}
-
-void DRW_shgroup_uniform_short_to_float(DRWShadingGroup *shgroup, const char *name, const short *value, int arraysize)
-{
- drw_interface_uniform(shgroup, name, DRW_UNIFORM_SHORT_TO_FLOAT, value, 1, arraysize);
-}
-
-void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
-{
- drw_interface_uniform(shgroup, name, DRW_UNIFORM_INT, value, 1, arraysize);
-}
-
-void DRW_shgroup_uniform_ivec2(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
-{
- drw_interface_uniform(shgroup, name, DRW_UNIFORM_INT, value, 2, arraysize);
-}
-
-void DRW_shgroup_uniform_ivec3(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
-{
- drw_interface_uniform(shgroup, name, DRW_UNIFORM_INT, value, 3, arraysize);
-}
-
-void DRW_shgroup_uniform_mat3(DRWShadingGroup *shgroup, const char *name, const float *value)
-{
- drw_interface_uniform(shgroup, name, DRW_UNIFORM_MAT3, value, 9, 1);
-}
-
-void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float *value)
-{
- drw_interface_uniform(shgroup, name, DRW_UNIFORM_MAT4, value, 16, 1);
-}
-
-/* Creates a VBO containing OGL primitives for all DRWCallDynamic */
-static void shgroup_dynamic_batch(DRWShadingGroup *shgroup)
-{
- DRWInterface *interface = &shgroup->interface;
- int nbr = interface->instance_count;
-
- Gwn_PrimType type = (shgroup->type == DRW_SHG_POINT_BATCH) ? GWN_PRIM_POINTS :
- (shgroup->type == DRW_SHG_TRIANGLE_BATCH) ? GWN_PRIM_TRIS : GWN_PRIM_LINES;
-
- if (nbr == 0)
- return;
-
- /* Upload Data */
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&interface->vbo_format);
- if (interface->inst_data) {
- GWN_vertbuf_data_set(vbo, nbr, DRW_instance_data_get(interface->inst_data), false);
- } else {
- /* Use unitialized memory. This is for dummy vertex buffers. */
- /* XXX TODO do not alloc at all. */
- GWN_vertbuf_data_alloc(vbo, nbr);
- }
-
- /* TODO make the batch dynamic instead of freeing it every times */
- if (shgroup->batch_geom)
- GWN_batch_discard(shgroup->batch_geom);
-
- shgroup->batch_geom = GWN_batch_create_ex(type, vbo, NULL, GWN_BATCH_OWNS_VBO);
-}
-
-static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
-{
- DRWInterface *interface = &shgroup->interface;
- int buffer_size = 0;
- void *data = NULL;
-
- if (interface->instance_batch != NULL) {
- return;
- }
-
- /* TODO We still need this because gawain does not support Matrix attribs. */
- if (interface->instance_count == 0) {
- if (interface->instance_vbo) {
- glDeleteBuffers(1, &interface->instance_vbo);
- interface->instance_vbo = 0;
- }
- return;
- }
-
- /* Gather Data */
- buffer_size = sizeof(float) * interface->attribs_stride * interface->instance_count;
-
- /* TODO poke mike to add this to gawain */
- if (interface->instance_vbo) {
- glDeleteBuffers(1, &interface->instance_vbo);
- interface->instance_vbo = 0;
- }
-
- if (interface->inst_data) {
- data = DRW_instance_data_get(interface->inst_data);
- }
-
- glGenBuffers(1, &interface->instance_vbo);
- glBindBuffer(GL_ARRAY_BUFFER, interface->instance_vbo);
- glBufferData(GL_ARRAY_BUFFER, buffer_size, data, GL_STATIC_DRAW);
-}
-
-static void shgroup_dynamic_batch_from_calls(DRWShadingGroup *shgroup)
-{
- if ((shgroup->interface.instance_vbo || shgroup->batch_geom) &&
- (G.debug_value == 667))
- {
- return;
- }
-
- if (shgroup->type == DRW_SHG_INSTANCE) {
- shgroup_dynamic_instance(shgroup);
- }
- else {
- shgroup_dynamic_batch(shgroup);
- }
-}
-
-/** \} */
-
-
-/* -------------------------------------------------------------------- */
-
-/** \name Passes (DRW_pass)
- * \{ */
-
-DRWPass *DRW_pass_create(const char *name, DRWState state)
-{
- DRWPass *pass = BLI_mempool_alloc(DST.vmempool->passes);
- pass->state = state;
- BLI_strncpy(pass->name, name, MAX_PASS_NAME);
-
- pass->shgroups = NULL;
- pass->shgroups_last = NULL;
-
- return pass;
-}
-
-void DRW_pass_state_set(DRWPass *pass, DRWState state)
-{
- pass->state = state;
-}
-
-void DRW_pass_free(DRWPass *pass)
-{
- for (DRWShadingGroup *shgroup = pass->shgroups; shgroup; shgroup = shgroup->next) {
- DRW_shgroup_free(shgroup);
- }
-
- pass->shgroups = NULL;
- pass->shgroups_last = NULL;
-}
-
-void DRW_pass_foreach_shgroup(DRWPass *pass, void (*callback)(void *userData, DRWShadingGroup *shgrp), void *userData)
-{
- for (DRWShadingGroup *shgroup = pass->shgroups; shgroup; shgroup = shgroup->next) {
- callback(userData, shgroup);
- }
-}
-
-typedef struct ZSortData {
- float *axis;
- float *origin;
-} ZSortData;
-
-static int pass_shgroup_dist_sort(void *thunk, const void *a, const void *b)
-{
- const ZSortData *zsortdata = (ZSortData *)thunk;
- const DRWShadingGroup *shgrp_a = (const DRWShadingGroup *)a;
- const DRWShadingGroup *shgrp_b = (const DRWShadingGroup *)b;
-
- const DRWCall *call_a;
- const DRWCall *call_b;
-
- call_a = shgrp_a->calls_first;
- call_b = shgrp_b->calls_first;
-
- if (call_a == NULL) return -1;
- if (call_b == NULL) return -1;
-
- float tmp[3];
- sub_v3_v3v3(tmp, zsortdata->origin, call_a->obmat[3]);
- const float a_sq = dot_v3v3(zsortdata->axis, tmp);
- sub_v3_v3v3(tmp, zsortdata->origin, call_b->obmat[3]);
- const float b_sq = dot_v3v3(zsortdata->axis, tmp);
-
- if (a_sq < b_sq) return 1;
- else if (a_sq > b_sq) return -1;
- else {
- /* If there is a depth prepass put it before */
- if ((shgrp_a->state_extra & DRW_STATE_WRITE_DEPTH) != 0) {
- return -1;
- }
- else if ((shgrp_b->state_extra & DRW_STATE_WRITE_DEPTH) != 0) {
- return 1;
- }
- else return 0;
- }
-}
-
-/* ------------------ Shading group sorting --------------------- */
-
-#define SORT_IMPL_LINKTYPE DRWShadingGroup
-
-#define SORT_IMPL_USE_THUNK
-#define SORT_IMPL_FUNC shgroup_sort_fn_r
-#include "../../blenlib/intern/list_sort_impl.h"
-#undef SORT_IMPL_FUNC
-#undef SORT_IMPL_USE_THUNK
-
-#undef SORT_IMPL_LINKTYPE
-
-/**
- * Sort Shading groups by decreasing Z of their first draw call.
- * This is usefull for order dependant effect such as transparency.
- **/
-void DRW_pass_sort_shgroup_z(DRWPass *pass)
-{
- RegionView3D *rv3d = DST.draw_ctx.rv3d;
-
- float (*viewinv)[4];
- viewinv = (viewport_matrix_override.override[DRW_MAT_VIEWINV])
- ? viewport_matrix_override.mat[DRW_MAT_VIEWINV] : rv3d->viewinv;
-
- ZSortData zsortdata = {viewinv[2], viewinv[3]};
-
- if (pass->shgroups && pass->shgroups->next) {
- pass->shgroups = shgroup_sort_fn_r(pass->shgroups, pass_shgroup_dist_sort, &zsortdata);
-
- /* Find the next last */
- DRWShadingGroup *last = pass->shgroups;
- while ((last = last->next)) {
- /* Do nothing */
- }
- pass->shgroups_last = last;
- }
-}
-
-/** \} */
-
-
-/* -------------------------------------------------------------------- */
-
-/** \name Draw (DRW_draw)
- * \{ */
-
-static void drw_state_set(DRWState state)
-{
- if (DST.state == state) {
- return;
- }
-
-
-#define CHANGED_TO(f) \
- ((DST.state & (f)) ? \
- ((state & (f)) ? 0 : -1) : \
- ((state & (f)) ? 1 : 0))
-
-#define CHANGED_ANY(f) \
- ((DST.state & (f)) != (state & (f)))
-
-#define CHANGED_ANY_STORE_VAR(f, enabled) \
- ((DST.state & (f)) != (enabled = (state & (f))))
-
- /* Depth Write */
- {
- int test;
- if ((test = CHANGED_TO(DRW_STATE_WRITE_DEPTH))) {
- if (test == 1) {
- glDepthMask(GL_TRUE);
- }
- else {
- glDepthMask(GL_FALSE);
- }
- }
- }
-
- /* Color Write */
- {
- int test;
- if ((test = CHANGED_TO(DRW_STATE_WRITE_COLOR))) {
- if (test == 1) {
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- }
- else {
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- }
- }
- }
-
- /* Cull */
- {
- DRWState test;
- if (CHANGED_ANY_STORE_VAR(
- DRW_STATE_CULL_BACK | DRW_STATE_CULL_FRONT,
- test))
- {
- if (test) {
- glEnable(GL_CULL_FACE);
-
- if ((state & DRW_STATE_CULL_BACK) != 0) {
- glCullFace(GL_BACK);
- }
- else if ((state & DRW_STATE_CULL_FRONT) != 0) {
- glCullFace(GL_FRONT);
- }
- else {
- BLI_assert(0);
- }
- }
- else {
- glDisable(GL_CULL_FACE);
- }
- }
- }
-
- /* Depth Test */
- {
- DRWState test;
- if (CHANGED_ANY_STORE_VAR(
- DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER | DRW_STATE_DEPTH_ALWAYS,
- test))
- {
- if (test) {
- glEnable(GL_DEPTH_TEST);
-
- if (state & DRW_STATE_DEPTH_LESS) {
- glDepthFunc(GL_LEQUAL);
- }
- else if (state & DRW_STATE_DEPTH_EQUAL) {
- glDepthFunc(GL_EQUAL);
- }
- else if (state & DRW_STATE_DEPTH_GREATER) {
- glDepthFunc(GL_GREATER);
- }
- else if (state & DRW_STATE_DEPTH_ALWAYS) {
- glDepthFunc(GL_ALWAYS);
- }
- else {
- BLI_assert(0);
- }
- }
- else {
- glDisable(GL_DEPTH_TEST);
- }
- }
- }
-
- /* Wire Width */
- {
- if (CHANGED_ANY(DRW_STATE_WIRE | DRW_STATE_WIRE_LARGE)) {
- if ((state & DRW_STATE_WIRE) != 0) {
- glLineWidth(1.0f);
- }
- else if ((state & DRW_STATE_WIRE_LARGE) != 0) {
- glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
- }
- else {
- /* do nothing */
- }
- }
- }
-
- /* Points Size */
- {
- int test;
- if ((test = CHANGED_TO(DRW_STATE_POINT))) {
- if (test == 1) {
- GPU_enable_program_point_size();
- glPointSize(5.0f);
- }
- else {
- GPU_disable_program_point_size();
- }
- }
- }
-
- /* Blending (all buffer) */
- {
- int test;
- if (CHANGED_ANY_STORE_VAR(
- DRW_STATE_BLEND | DRW_STATE_ADDITIVE | DRW_STATE_MULTIPLY | DRW_STATE_TRANSMISSION |
- DRW_STATE_ADDITIVE_FULL,
- test))
- {
- if (test) {
- glEnable(GL_BLEND);
-
- if ((state & DRW_STATE_BLEND) != 0) {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, /* RGB */
- GL_ONE, GL_ONE_MINUS_SRC_ALPHA); /* Alpha */
- }
- else if ((state & DRW_STATE_MULTIPLY) != 0) {
- glBlendFunc(GL_DST_COLOR, GL_ZERO);
- }
- else if ((state & DRW_STATE_TRANSMISSION) != 0) {
- glBlendFunc(GL_ONE, GL_SRC_ALPHA);
- }
- else if ((state & DRW_STATE_ADDITIVE) != 0) {
- /* Do not let alpha accumulate but premult the source RGB by it. */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, /* RGB */
- GL_ZERO, GL_ONE); /* Alpha */
- }
- else if ((state & DRW_STATE_ADDITIVE_FULL) != 0) {
- /* Let alpha accumulate. */
- glBlendFunc(GL_ONE, GL_ONE);
- }
- else {
- BLI_assert(0);
- }
- }
- else {
- glDisable(GL_BLEND);
- }
- }
- }
-
- /* Clip Planes */
- {
- int test;
- if ((test = CHANGED_TO(DRW_STATE_CLIP_PLANES))) {
- if (test == 1) {
- for (int i = 0; i < DST.num_clip_planes; ++i) {
- glEnable(GL_CLIP_DISTANCE0 + i);
- }
- }
- else {
- for (int i = 0; i < MAX_CLIP_PLANES; ++i) {
- glDisable(GL_CLIP_DISTANCE0 + i);
- }
- }
- }
- }
-
- /* Line Stipple */
- {
- int test;
- if (CHANGED_ANY_STORE_VAR(
- DRW_STATE_STIPPLE_2 | DRW_STATE_STIPPLE_3 | DRW_STATE_STIPPLE_4,
- test))
- {
- if (test) {
- if ((state & DRW_STATE_STIPPLE_2) != 0) {
- setlinestyle(2);
- }
- else if ((state & DRW_STATE_STIPPLE_3) != 0) {
- setlinestyle(3);
- }
- else if ((state & DRW_STATE_STIPPLE_4) != 0) {
- setlinestyle(4);
- }
- else {
- BLI_assert(0);
- }
- }
- else {
- setlinestyle(0);
- }
- }
- }
-
- /* Stencil */
- {
- DRWState test;
- if (CHANGED_ANY_STORE_VAR(
- DRW_STATE_WRITE_STENCIL |
- DRW_STATE_STENCIL_EQUAL,
- test))
- {
- if (test) {
- glEnable(GL_STENCIL_TEST);
-
- /* Stencil Write */
- if ((state & DRW_STATE_WRITE_STENCIL) != 0) {
- glStencilMask(0xFF);
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
- }
- /* Stencil Test */
- else if ((state & DRW_STATE_STENCIL_EQUAL) != 0) {
- glStencilMask(0x00); /* disable write */
- DST.stencil_mask = 0;
- }
- else {
- BLI_assert(0);
- }
- }
- else {
- /* disable write & test */
- DST.stencil_mask = 0;
- glStencilMask(0x00);
- glStencilFunc(GL_ALWAYS, 1, 0xFF);
- glDisable(GL_STENCIL_TEST);
- }
- }
- }
-
-#undef CHANGED_TO
-#undef CHANGED_ANY
-#undef CHANGED_ANY_STORE_VAR
-
- DST.state = state;
-}
-
-static void drw_stencil_set(unsigned int mask)
-{
- if (DST.stencil_mask != mask) {
- /* Stencil Write */
- if ((DST.state & DRW_STATE_WRITE_STENCIL) != 0) {
- glStencilFunc(GL_ALWAYS, mask, 0xFF);
- DST.stencil_mask = mask;
- }
- /* Stencil Test */
- else if ((DST.state & DRW_STATE_STENCIL_EQUAL) != 0) {
- glStencilFunc(GL_EQUAL, mask, 0xFF);
- DST.stencil_mask = mask;
- }
- }
-}
-
-typedef struct DRWBoundTexture {
- struct DRWBoundTexture *next, *prev;
- GPUTexture *tex;
-} DRWBoundTexture;
-
-static void draw_geometry_prepare(
- DRWShadingGroup *shgroup, const float (*obmat)[4], const float *texcoloc, const float *texcosize)
-{
- RegionView3D *rv3d = DST.draw_ctx.rv3d;
- DRWInterface *interface = &shgroup->interface;
-
- float mvp[4][4], mv[4][4], mi[4][4], mvi[4][4], pi[4][4], n[3][3], wn[3][3];
- float orcofacs[2][3] = {{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}};
- float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */
-
- bool do_pi = (interface->projectioninverse != -1);
- bool do_mvp = (interface->modelviewprojection != -1);
- bool do_mi = (interface->modelinverse != -1);
- bool do_mv = (interface->modelview != -1);
- bool do_mvi = (interface->modelviewinverse != -1);
- bool do_n = (interface->normal != -1);
- bool do_wn = (interface->worldnormal != -1);
- bool do_eye = (interface->eye != -1);
- bool do_orco = (interface->orcotexfac != -1) && (texcoloc != NULL) && (texcosize != NULL);
-
- /* Matrix override */
- float (*persmat)[4];
- float (*persinv)[4];
- float (*viewmat)[4];
- float (*viewinv)[4];
- float (*winmat)[4];
- float (*wininv)[4];
-
- persmat = (viewport_matrix_override.override[DRW_MAT_PERS])
- ? viewport_matrix_override.mat[DRW_MAT_PERS] : rv3d->persmat;
- persinv = (viewport_matrix_override.override[DRW_MAT_PERSINV])
- ? viewport_matrix_override.mat[DRW_MAT_PERSINV] : rv3d->persinv;
- viewmat = (viewport_matrix_override.override[DRW_MAT_VIEW])
- ? viewport_matrix_override.mat[DRW_MAT_VIEW] : rv3d->viewmat;
- viewinv = (viewport_matrix_override.override[DRW_MAT_VIEWINV])
- ? viewport_matrix_override.mat[DRW_MAT_VIEWINV] : rv3d->viewinv;
- winmat = (viewport_matrix_override.override[DRW_MAT_WIN])
- ? viewport_matrix_override.mat[DRW_MAT_WIN] : rv3d->winmat;
- wininv = viewport_matrix_override.mat[DRW_MAT_WININV];
-
- if (do_pi) {
- if (!viewport_matrix_override.override[DRW_MAT_WININV]) {
- invert_m4_m4(pi, winmat);
- wininv = pi;
- }
- }
- if (do_mi) {
- invert_m4_m4(mi, obmat);
- }
- if (do_mvp) {
- mul_m4_m4m4(mvp, persmat, obmat);
- }
- if (do_mv || do_mvi || do_n || do_eye) {
- mul_m4_m4m4(mv, viewmat, obmat);
- }
- if (do_mvi) {
- invert_m4_m4(mvi, mv);
- }
- if (do_n || do_eye) {
- copy_m3_m4(n, mv);
- invert_m3(n);
- transpose_m3(n);
- }
- if (do_wn) {
- copy_m3_m4(wn, obmat);
- invert_m3(wn);
- transpose_m3(wn);
- }
- if (do_eye) {
- /* Used by orthographic wires */
- float tmp[3][3];
- invert_m3_m3(tmp, n);
- /* set eye vector, transformed to object coords */
- mul_m3_v3(tmp, eye);
- }
- if (do_orco) {
- mul_v3_v3fl(orcofacs[1], texcosize, 2.0f);
- invert_v3(orcofacs[1]);
- sub_v3_v3v3(orcofacs[0], texcoloc, texcosize);
- negate_v3(orcofacs[0]);
- mul_v3_v3(orcofacs[0], orcofacs[1]); /* result in a nice MADD in the shader */
- }
-
- /* Should be really simple */
- /* step 1 : bind object dependent matrices */
- /* TODO : Some of these are not object dependant.
- * They should be grouped inside a UBO updated once per redraw.
- * The rest can also go into a UBO to reduce API calls. */
- GPU_shader_uniform_vector(shgroup->shader, interface->model, 16, 1, (float *)obmat);
- GPU_shader_uniform_vector(shgroup->shader, interface->modelinverse, 16, 1, (float *)mi);
- GPU_shader_uniform_vector(shgroup->shader, interface->modelviewprojection, 16, 1, (float *)mvp);
- GPU_shader_uniform_vector(shgroup->shader, interface->viewinverse, 16, 1, (float *)viewinv);
- GPU_shader_uniform_vector(shgroup->shader, interface->viewprojection, 16, 1, (float *)persmat);
- GPU_shader_uniform_vector(shgroup->shader, interface->viewprojectioninverse, 16, 1, (float *)persinv);
- GPU_shader_uniform_vector(shgroup->shader, interface->projection, 16, 1, (float *)winmat);
- GPU_shader_uniform_vector(shgroup->shader, interface->projectioninverse, 16, 1, (float *)wininv);
- GPU_shader_uniform_vector(shgroup->shader, interface->view, 16, 1, (float *)viewmat);
- GPU_shader_uniform_vector(shgroup->shader, interface->modelview, 16, 1, (float *)mv);
- GPU_shader_uniform_vector(shgroup->shader, interface->modelviewinverse, 16, 1, (float *)mvi);
- GPU_shader_uniform_vector(shgroup->shader, interface->normal, 9, 1, (float *)n);
- GPU_shader_uniform_vector(shgroup->shader, interface->worldnormal, 9, 1, (float *)wn);
- GPU_shader_uniform_vector(shgroup->shader, interface->camtexfac, 4, 1, (float *)rv3d->viewcamtexcofac);
- GPU_shader_uniform_vector(shgroup->shader, interface->orcotexfac, 3, 2, (float *)orcofacs);
- GPU_shader_uniform_vector(shgroup->shader, interface->eye, 3, 1, (float *)eye);
- GPU_shader_uniform_vector(shgroup->shader, interface->clipplanes, 4, DST.num_clip_planes, (float *)DST.clip_planes_eq);
-}
-
-static void draw_geometry_execute_ex(
- DRWShadingGroup *shgroup, Gwn_Batch *geom, unsigned int start, unsigned int count)
-{
- DRWInterface *interface = &shgroup->interface;
- /* step 2 : bind vertex array & draw */
- GWN_batch_program_set(geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
- if (interface->instance_batch) {
- /* Used for Particles. Cannot do partial drawing. */
- GWN_batch_draw_stupid_instanced_with_batch(geom, interface->instance_batch);
- }
- else if (interface->instance_vbo) {
- GWN_batch_draw_stupid_instanced(
- geom, interface->instance_vbo, start, count, interface->attribs_count,
- interface->attribs_stride, interface->attribs_size, interface->attribs_loc);
- }
- else {
- GWN_batch_draw_stupid(geom, start, count);
- }
- /* XXX this just tells gawain we are done with the shader.
- * This does not unbind the shader. */
- GWN_batch_program_unset(geom);
-}
-
-static void draw_geometry_execute(DRWShadingGroup *shgroup, Gwn_Batch *geom)
-{
- draw_geometry_execute_ex(shgroup, geom, 0, 0);
-}
-
-static void draw_geometry(
- DRWShadingGroup *shgroup, Gwn_Batch *geom, const float (*obmat)[4], ID *ob_data,
- unsigned int start, unsigned int count)
-{
- float *texcoloc = NULL;
- float *texcosize = NULL;
-
- if (ob_data != NULL) {
- switch (GS(ob_data->name)) {
- case ID_ME:
- BKE_mesh_texspace_get_reference((Mesh *)ob_data, NULL, &texcoloc, NULL, &texcosize);
- break;
- case ID_CU:
- {
- Curve *cu = (Curve *)ob_data;
- if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_DIRTY)) {
- BKE_curve_texspace_calc(cu);
- }
- texcoloc = cu->loc;
- texcosize = cu->size;
- break;
- }
- case ID_MB:
- {
- MetaBall *mb = (MetaBall *)ob_data;
- texcoloc = mb->loc;
- texcosize = mb->size;
- break;
- }
- default:
- break;
- }
- }
-
- draw_geometry_prepare(shgroup, obmat, texcoloc, texcosize);
-
- draw_geometry_execute_ex(shgroup, geom, start, count);
-}
-
-static void bind_texture(GPUTexture *tex)
-{
- int bind_num = GPU_texture_bound_number(tex);
- if (bind_num == -1) {
- for (int i = 0; i < GPU_max_textures(); ++i) {
- RST.bind_tex_inc = (RST.bind_tex_inc + 1) % GPU_max_textures();
- if (RST.bound_tex_slots[RST.bind_tex_inc] == false) {
- if (RST.bound_texs[RST.bind_tex_inc] != NULL) {
- GPU_texture_unbind(RST.bound_texs[RST.bind_tex_inc]);
- }
- GPU_texture_bind(tex, RST.bind_tex_inc);
- RST.bound_texs[RST.bind_tex_inc] = tex;
- RST.bound_tex_slots[RST.bind_tex_inc] = true;
- return;
- }
- }
-
- printf("Not enough texture slots! Reduce number of textures used by your shader.\n");
- }
- RST.bound_tex_slots[bind_num] = true;
-}
-
-static void bind_ubo(GPUUniformBuffer *ubo)
-{
- if (RST.bind_ubo_inc < GPU_max_ubo_binds()) {
- GPU_uniformbuffer_bind(ubo, RST.bind_ubo_inc);
- RST.bind_ubo_inc++;
- }
- else {
- /* This is not depending on user input.
- * It is our responsability to make sure there enough slots. */
- BLI_assert(0 && "Not enough ubo slots! This should not happen!\n");
-
- /* printf so user can report bad behaviour */
- printf("Not enough ubo slots! This should not happen!\n");
- }
-}
-
-static void release_texture_slots(void)
-{
- memset(RST.bound_tex_slots, 0x0, sizeof(bool) * GPU_max_textures());
-}
-
-static void release_ubo_slots(void)
+#ifdef DEBUG
+static void drw_state_ensure_not_reused(DRWManager *dst)
{
- RST.bind_ubo_inc = 0;
+ memset(dst, 0xff, offsetof(DRWManager, ogl_context));
}
-
-static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
-{
- BLI_assert(shgroup->shader);
-
- DRWInterface *interface = &shgroup->interface;
- GPUTexture *tex;
- GPUUniformBuffer *ubo;
- int val;
- float fval;
-
- if (DST.shader != shgroup->shader) {
- if (DST.shader) GPU_shader_unbind();
- GPU_shader_bind(shgroup->shader);
- DST.shader = shgroup->shader;
- }
-
- const bool is_normal = ELEM(shgroup->type, DRW_SHG_NORMAL);
-
- if (!is_normal) {
- shgroup_dynamic_batch_from_calls(shgroup);
- }
-
- release_texture_slots();
- release_ubo_slots();
-
- drw_state_set((pass_state & shgroup->state_extra_disable) | shgroup->state_extra);
- drw_stencil_set(shgroup->stencil_mask);
-
- /* Binding Uniform */
- /* Don't check anything, Interface should already contain the least uniform as possible */
- for (DRWUniform *uni = interface->uniforms; uni; uni = uni->next) {
- switch (uni->type) {
- case DRW_UNIFORM_SHORT_TO_INT:
- val = (int)*((short *)uni->value);
- GPU_shader_uniform_vector_int(
- shgroup->shader, uni->location, uni->length, uni->arraysize, (int *)&val);
- break;
- case DRW_UNIFORM_SHORT_TO_FLOAT:
- fval = (float)*((short *)uni->value);
- GPU_shader_uniform_vector(
- shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)&fval);
- break;
- case DRW_UNIFORM_BOOL:
- case DRW_UNIFORM_INT:
- GPU_shader_uniform_vector_int(
- shgroup->shader, uni->location, uni->length, uni->arraysize, (int *)uni->value);
- break;
- case DRW_UNIFORM_FLOAT:
- case DRW_UNIFORM_MAT3:
- case DRW_UNIFORM_MAT4:
- GPU_shader_uniform_vector(
- shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)uni->value);
- break;
- case DRW_UNIFORM_TEXTURE:
- tex = (GPUTexture *)uni->value;
- BLI_assert(tex);
- bind_texture(tex);
- GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
- break;
- case DRW_UNIFORM_BUFFER:
- if (!DRW_state_is_fbo()) {
- break;
- }
- tex = *((GPUTexture **)uni->value);
- BLI_assert(tex);
- bind_texture(tex);
- GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
- break;
- case DRW_UNIFORM_BLOCK:
- ubo = (GPUUniformBuffer *)uni->value;
- bind_ubo(ubo);
- GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
- break;
- }
- }
-
-#ifdef USE_GPU_SELECT
- /* use the first item because of selection we only ever add one */
-# define GPU_SELECT_LOAD_IF_PICKSEL(_call) \
- if ((G.f & G_PICKSEL) && (_call)) { \
- GPU_select_load_id((_call)->head.select_id); \
- } ((void)0)
-
-# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_shgroup, _start, _count) \
- _start = 0; \
- _count = _shgroup->interface.instance_count; \
- int *select_id = NULL; \
- if (G.f & G_PICKSEL) { \
- if (_shgroup->interface.override_selectid == -1) { \
- select_id = DRW_instance_data_get(_shgroup->interface.inst_selectid); \
- switch (_shgroup->type) { \
- case DRW_SHG_TRIANGLE_BATCH: _count = 3; break; \
- case DRW_SHG_LINE_BATCH: _count = 2; break; \
- default: _count = 1; break; \
- } \
- } \
- else { \
- GPU_select_load_id(_shgroup->interface.override_selectid); \
- } \
- } \
- while (_start < _shgroup->interface.instance_count) { \
- if (select_id) { \
- GPU_select_load_id(select_id[_start]); \
- }
-
-# define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(_start, _count) \
- _start += _count; \
- }
-
-#else
-# define GPU_SELECT_LOAD_IF_PICKSEL(call)
-# define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count)
-# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_shgroup, _start, _count) \
- _start = 0; \
- _count = _shgroup->interface.instance_count;
-
#endif
- /* Rendering Calls */
- if (!is_normal) {
- /* Replacing multiple calls with only one */
- float obmat[4][4];
- unit_m4(obmat);
-
- if (shgroup->type == DRW_SHG_INSTANCE &&
- (interface->instance_count > 0 || interface->instance_batch != NULL))
- {
- if (interface->instance_batch != NULL) {
- GPU_SELECT_LOAD_IF_PICKSEL((DRWCall *)shgroup->calls_first);
- draw_geometry(shgroup, shgroup->instance_geom, obmat, shgroup->instance_data, 0, 0);
- }
- else {
- unsigned int count, start;
- GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup, start, count)
- {
- draw_geometry(shgroup, shgroup->instance_geom, obmat, shgroup->instance_data, start, count);
- }
- GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count)
- }
- }
- else {
- /* Some dynamic batch can have no geom (no call to aggregate) */
- if (shgroup->batch_geom) {
- unsigned int count, start;
- GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup, start, count)
- {
- draw_geometry(shgroup, shgroup->batch_geom, obmat, NULL, start, count);
- }
- GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count)
- }
- }
- }
- else {
- for (DRWCall *call = shgroup->calls_first; call; call = call->head.prev) {
- bool neg_scale = is_negative_m4(call->obmat);
-
- /* Negative scale objects */
- if (neg_scale) {
- glFrontFace(DST.backface);
- }
-
- GPU_SELECT_LOAD_IF_PICKSEL(call);
-
- if (call->head.type == DRW_CALL_SINGLE) {
- draw_geometry(shgroup, call->geometry, call->obmat, call->ob_data, 0, 0);
- }
- else {
- BLI_assert(call->head.type == DRW_CALL_GENERATE);
- DRWCallGenerate *callgen = ((DRWCallGenerate *)call);
- draw_geometry_prepare(shgroup, callgen->obmat, NULL, NULL);
- callgen->geometry_fn(shgroup, draw_geometry_execute, callgen->user_data);
- }
-
- /* Reset state */
- if (neg_scale) {
- glFrontFace(DST.frontface);
- }
- }
- }
-
- /* TODO: remove, (currently causes alpha issue with sculpt, need to investigate) */
- DRW_state_reset();
-}
-
-static void drw_draw_pass_ex(DRWPass *pass, DRWShadingGroup *start_group, DRWShadingGroup *end_group)
-{
- /* Start fresh */
- DST.shader = NULL;
-
- drw_state_set(pass->state);
-
- DRW_stats_query_start(pass->name);
-
- for (DRWShadingGroup *shgroup = start_group; shgroup; shgroup = shgroup->next) {
- draw_shgroup(shgroup, pass->state);
- /* break if upper limit */
- if (shgroup == end_group) {
- break;
- }
- }
-
- /* Clear Bound textures */
- for (int i = 0; i < GPU_max_textures(); i++) {
- if (RST.bound_texs[i] != NULL) {
- GPU_texture_unbind(RST.bound_texs[i]);
- RST.bound_texs[i] = NULL;
- }
- }
-
- if (DST.shader) {
- GPU_shader_unbind();
- DST.shader = NULL;
- }
-
- DRW_stats_query_end();
-}
-
-void DRW_draw_pass(DRWPass *pass)
-{
- drw_draw_pass_ex(pass, pass->shgroups, pass->shgroups_last);
-}
-
-/* Draw only a subset of shgroups. Used in special situations as grease pencil strokes */
-void DRW_draw_pass_subset(DRWPass *pass, DRWShadingGroup *start_group, DRWShadingGroup *end_group)
-{
- drw_draw_pass_ex(pass, start_group, end_group);
-}
+/* -------------------------------------------------------------------- */
void DRW_draw_callbacks_pre_scene(void)
{
@@ -2142,46 +128,6 @@ void DRW_draw_callbacks_post_scene(void)
gpuLoadMatrix(rv3d->viewmat);
}
-/* Reset state to not interfer with other UI drawcall */
-void DRW_state_reset_ex(DRWState state)
-{
- DST.state = ~state;
- drw_state_set(state);
-}
-
-void DRW_state_reset(void)
-{
- /* Reset blending function */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- DRW_state_reset_ex(DRW_STATE_DEFAULT);
-}
-
-/* NOTE : Make sure to reset after use! */
-void DRW_state_invert_facing(void)
-{
- SWAP(GLenum, DST.backface, DST.frontface);
- glFrontFace(DST.frontface);
-}
-
-/**
- * This only works if DRWPasses have been tagged with DRW_STATE_CLIP_PLANES,
- * and if the shaders have support for it (see usage of gl_ClipDistance).
- * Be sure to call DRW_state_clip_planes_reset() after you finish drawing.
- **/
-void DRW_state_clip_planes_add(float plane_eq[4])
-{
- copy_v4_v4(DST.clip_planes_eq[DST.num_clip_planes++], plane_eq);
-}
-
-void DRW_state_clip_planes_reset(void)
-{
- DST.num_clip_planes = 0;
-}
-
-/** \} */
-
-
struct DRWTextStore *DRW_text_cache_ensure(void)
{
BLI_assert(DST.text_store_p);
@@ -2199,13 +145,10 @@ struct DRWTextStore *DRW_text_cache_ensure(void)
bool DRW_object_is_renderable(Object *ob)
{
- Scene *scene = DST.draw_ctx.scene;
- Object *obedit = scene->obedit;
-
BLI_assert(BKE_object_is_visible(ob, OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE));
if (ob->type == OB_MESH) {
- if (ob == obedit) {
+ if (ob == DST.draw_ctx.object_edit) {
IDProperty *props = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_EDIT, "");
bool do_show_occlude_wire = BKE_collection_engine_property_value_get_bool(props, "show_occlude_wire");
if (do_show_occlude_wire) {
@@ -2250,8 +193,9 @@ bool DRW_object_is_flat_normal(const Object *ob)
int DRW_object_is_mode_shade(const Object *ob)
{
BLI_assert(ob == DST.draw_ctx.obact);
- if ((ob->mode & OB_MODE_EDIT) == 0) {
- if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) {
+ UNUSED_VARS_NDEBUG(ob);
+ if ((DST.draw_ctx.object_mode & OB_MODE_EDIT) == 0) {
+ if (DST.draw_ctx.object_mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) {
if ((DST.draw_ctx.v3d->flag2 & V3D_SHOW_MODE_SHADE_OVERRIDE) == 0) {
return true;
}
@@ -2268,188 +212,9 @@ int DRW_object_is_mode_shade(const Object *ob)
/* -------------------------------------------------------------------- */
-/** \name Framebuffers (DRW_framebuffer)
+/** \name Color Management
* \{ */
-static GPUTextureFormat convert_tex_format(
- int fbo_format,
- int *r_channels, bool *r_is_depth)
-{
- *r_is_depth = ELEM(fbo_format, DRW_TEX_DEPTH_16, DRW_TEX_DEPTH_24, DRW_TEX_DEPTH_24_STENCIL_8);
-
- switch (fbo_format) {
- case DRW_TEX_R_16: *r_channels = 1; return GPU_R16F;
- case DRW_TEX_R_32: *r_channels = 1; return GPU_R32F;
- case DRW_TEX_RG_8: *r_channels = 2; return GPU_RG8;
- case DRW_TEX_RG_16: *r_channels = 2; return GPU_RG16F;
- case DRW_TEX_RG_16I: *r_channels = 2; return GPU_RG16I;
- case DRW_TEX_RG_32: *r_channels = 2; return GPU_RG32F;
- case DRW_TEX_RGBA_8: *r_channels = 4; return GPU_RGBA8;
- case DRW_TEX_RGBA_16: *r_channels = 4; return GPU_RGBA16F;
- case DRW_TEX_RGBA_32: *r_channels = 4; return GPU_RGBA32F;
- case DRW_TEX_DEPTH_16: *r_channels = 1; return GPU_DEPTH_COMPONENT16;
- case DRW_TEX_DEPTH_24: *r_channels = 1; return GPU_DEPTH_COMPONENT24;
- case DRW_TEX_DEPTH_24_STENCIL_8: *r_channels = 1; return GPU_DEPTH24_STENCIL8;
- case DRW_TEX_DEPTH_32: *r_channels = 1; return GPU_DEPTH_COMPONENT32F;
- case DRW_TEX_RGB_11_11_10: *r_channels = 3; return GPU_R11F_G11F_B10F;
- default:
- BLI_assert(false && "Texture format unsupported as render target!");
- *r_channels = 4; return GPU_RGBA8;
- }
-}
-
-struct GPUFrameBuffer *DRW_framebuffer_create(void)
-{
- return GPU_framebuffer_create();
-}
-
-void DRW_framebuffer_init(
- struct GPUFrameBuffer **fb, void *engine_type, int width, int height,
- DRWFboTexture textures[MAX_FBO_TEX], int textures_len)
-{
- BLI_assert(textures_len <= MAX_FBO_TEX);
- BLI_assert(width > 0 && height > 0);
-
- bool create_fb = false;
- int color_attachment = -1;
-
- if (!*fb) {
- *fb = GPU_framebuffer_create();
- create_fb = true;
- }
-
- for (int i = 0; i < textures_len; ++i) {
- int channels;
- bool is_depth;
- bool create_tex = false;
-
- DRWFboTexture fbotex = textures[i];
- bool is_temp = (fbotex.flag & DRW_TEX_TEMP) != 0;
-
- GPUTextureFormat gpu_format = convert_tex_format(fbotex.format, &channels, &is_depth);
-
- if (!*fbotex.tex || is_temp) {
- /* Temp textures need to be queried each frame, others not. */
- if (is_temp) {
- *fbotex.tex = GPU_viewport_texture_pool_query(
- DST.viewport, engine_type, width, height, channels, gpu_format);
- }
- else {
- *fbotex.tex = GPU_texture_create_2D_custom(
- width, height, channels, gpu_format, NULL, NULL);
- create_tex = true;
- }
- }
-
- if (!is_depth) {
- ++color_attachment;
- }
-
- if (create_fb || create_tex) {
- drw_texture_set_parameters(*fbotex.tex, fbotex.flag);
- GPU_framebuffer_texture_attach(*fb, *fbotex.tex, color_attachment, 0);
- }
- }
-
- if (create_fb && (textures_len > 0)) {
- if (!GPU_framebuffer_check_valid(*fb, NULL)) {
- printf("Error invalid framebuffer\n");
- }
-
- /* Detach temp textures */
- for (int i = 0; i < textures_len; ++i) {
- DRWFboTexture fbotex = textures[i];
-
- if ((fbotex.flag & DRW_TEX_TEMP) != 0) {
- GPU_framebuffer_texture_detach(*fbotex.tex);
- }
- }
-
- GPU_framebuffer_bind(DST.default_framebuffer);
- }
-}
-
-void DRW_framebuffer_free(struct GPUFrameBuffer *fb)
-{
- GPU_framebuffer_free(fb);
-}
-
-void DRW_framebuffer_bind(struct GPUFrameBuffer *fb)
-{
- GPU_framebuffer_bind(fb);
-}
-
-void DRW_framebuffer_clear(bool color, bool depth, bool stencil, float clear_col[4], float clear_depth)
-{
- if (color) {
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glClearColor(clear_col[0], clear_col[1], clear_col[2], clear_col[3]);
- }
- if (depth) {
- glDepthMask(GL_TRUE);
- glClearDepth(clear_depth);
- }
- if (stencil) {
- glStencilMask(0xFF);
- }
- glClear(((color) ? GL_COLOR_BUFFER_BIT : 0) |
- ((depth) ? GL_DEPTH_BUFFER_BIT : 0) |
- ((stencil) ? GL_STENCIL_BUFFER_BIT : 0));
-}
-
-void DRW_framebuffer_read_data(int x, int y, int w, int h, int channels, int slot, float *data)
-{
- GLenum type;
- switch (channels) {
- case 1: type = GL_RED; break;
- case 2: type = GL_RG; break;
- case 3: type = GL_RGB; break;
- case 4: type = GL_RGBA; break;
- default:
- BLI_assert(false && "wrong number of read channels");
- return;
- }
- glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
- glReadPixels(x, y, w, h, type, GL_FLOAT, data);
-}
-
-void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
-{
- GPU_framebuffer_texture_attach(fb, tex, slot, mip);
-}
-
-void DRW_framebuffer_texture_layer_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int layer, int mip)
-{
- GPU_framebuffer_texture_layer_attach(fb, tex, slot, layer, mip);
-}
-
-void DRW_framebuffer_cubeface_attach(struct GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip)
-{
- GPU_framebuffer_texture_cubeface_attach(fb, tex, slot, face, mip);
-}
-
-void DRW_framebuffer_texture_detach(GPUTexture *tex)
-{
- GPU_framebuffer_texture_detach(tex);
-}
-
-void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer *fb_write, bool depth, bool stencil)
-{
- GPU_framebuffer_blit(fb_read, 0, fb_write, 0, depth, stencil);
-}
-
-void DRW_framebuffer_recursive_downsample(
- struct GPUFrameBuffer *fb, struct GPUTexture *tex, int num_iter,
- void (*callback)(void *userData, int level), void *userData)
-{
- GPU_framebuffer_recursive_downsample(fb, tex, num_iter, callback, userData);
-}
-
-void DRW_framebuffer_viewport_size(struct GPUFrameBuffer *UNUSED(fb_read), int x, int y, int w, int h)
-{
- glViewport(x, y, w, h);
-}
-
/* Use color management profile to draw texture to framebuffer */
void DRW_transform_to_display(GPUTexture *tex)
{
@@ -2518,7 +283,7 @@ void DRW_transform_to_display(GPUTexture *tex)
/** \name Viewport (DRW_viewport)
* \{ */
-static void *DRW_viewport_engine_data_ensure(void *engine_type)
+void *drw_viewport_engine_data_ensure(void *engine_type)
{
void *data = GPU_viewport_engine_data_get(DST.viewport, engine_type);
@@ -2550,7 +315,12 @@ void DRW_engine_viewport_data_size_get(
const float *DRW_viewport_size_get(void)
{
- return &DST.size[0];
+ return DST.size;
+}
+
+const float *DRW_viewport_invert_size_get(void)
+{
+ return DST.inv_size;
}
const float *DRW_viewport_screenvecs_get(void)
@@ -2569,17 +339,59 @@ static void drw_viewport_cache_resize(void)
GPU_viewport_cache_release(DST.viewport);
if (DST.vmempool != NULL) {
- BLI_mempool_clear_ex(DST.vmempool->calls, BLI_mempool_count(DST.vmempool->calls));
- BLI_mempool_clear_ex(DST.vmempool->calls_generate, BLI_mempool_count(DST.vmempool->calls_generate));
- BLI_mempool_clear_ex(DST.vmempool->shgroups, BLI_mempool_count(DST.vmempool->shgroups));
- BLI_mempool_clear_ex(DST.vmempool->uniforms, BLI_mempool_count(DST.vmempool->uniforms));
- BLI_mempool_clear_ex(DST.vmempool->passes, BLI_mempool_count(DST.vmempool->passes));
+ BLI_mempool_clear_ex(DST.vmempool->calls, BLI_mempool_len(DST.vmempool->calls));
+ BLI_mempool_clear_ex(DST.vmempool->states, BLI_mempool_len(DST.vmempool->states));
+ BLI_mempool_clear_ex(DST.vmempool->shgroups, BLI_mempool_len(DST.vmempool->shgroups));
+ BLI_mempool_clear_ex(DST.vmempool->uniforms, BLI_mempool_len(DST.vmempool->uniforms));
+ BLI_mempool_clear_ex(DST.vmempool->passes, BLI_mempool_len(DST.vmempool->passes));
}
DRW_instance_data_list_free_unused(DST.idatalist);
DRW_instance_data_list_resize(DST.idatalist);
}
+static void drw_state_eval_ctx_init(DRWManager *dst)
+{
+ DRWContextState *draw_ctx = &dst->draw_ctx;
+ DEG_evaluation_context_init_from_scene(
+ &draw_ctx->eval_ctx,
+ draw_ctx->scene,
+ draw_ctx->view_layer,
+ DST.options.is_scene_render ? DAG_EVAL_RENDER : DAG_EVAL_VIEWPORT);
+}
+
+/* Not a viewport variable, we could split this out. */
+static void drw_context_state_init(void)
+{
+ if (DST.draw_ctx.obact) {
+ DST.draw_ctx.object_mode = DST.draw_ctx.obact->mode;
+ }
+ else {
+ DST.draw_ctx.object_mode = OB_MODE_OBJECT;
+ }
+
+ /* Edit object. */
+ if (DST.draw_ctx.object_mode & OB_MODE_EDIT) {
+ DST.draw_ctx.object_edit = DST.draw_ctx.obact;
+ }
+ else {
+ DST.draw_ctx.object_edit = NULL;
+ }
+
+ /* Pose object. */
+ if (DST.draw_ctx.object_mode & OB_MODE_POSE) {
+ DST.draw_ctx.object_pose = DST.draw_ctx.obact;
+ }
+ else if (DST.draw_ctx.object_mode & OB_MODE_WEIGHT_PAINT) {
+ DST.draw_ctx.object_pose = BKE_object_pose_armature_get(DST.draw_ctx.obact);
+ }
+ else {
+ DST.draw_ctx.object_pose = NULL;
+ }
+
+ drw_state_eval_ctx_init(&DST);
+}
+
/* It also stores viewport variable to an immutable place: DST
* This is because a cache uniform only store reference
* to its value. And we don't want to invalidate the cache
@@ -2587,13 +399,14 @@ static void drw_viewport_cache_resize(void)
static void drw_viewport_var_init(void)
{
RegionView3D *rv3d = DST.draw_ctx.rv3d;
-
/* Refresh DST.size */
if (DST.viewport) {
int size[2];
GPU_viewport_size_get(DST.viewport, size);
DST.size[0] = size[0];
DST.size[1] = size[1];
+ DST.inv_size[0] = 1.0f / size[0];
+ DST.inv_size[1] = 1.0f / size[1];
DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get(DST.viewport);
DST.default_framebuffer = fbl->default_fb;
@@ -2603,8 +416,8 @@ static void drw_viewport_var_init(void)
if (DST.vmempool->calls == NULL) {
DST.vmempool->calls = BLI_mempool_create(sizeof(DRWCall), 0, 512, 0);
}
- if (DST.vmempool->calls_generate == NULL) {
- DST.vmempool->calls_generate = BLI_mempool_create(sizeof(DRWCallGenerate), 0, 512, 0);
+ if (DST.vmempool->states == NULL) {
+ DST.vmempool->states = BLI_mempool_create(sizeof(DRWCallState), 0, 512, BLI_MEMPOOL_ALLOW_ITER);
}
if (DST.vmempool->shgroups == NULL) {
DST.vmempool->shgroups = BLI_mempool_create(sizeof(DRWShadingGroup), 0, 256, 0);
@@ -2623,88 +436,132 @@ static void drw_viewport_var_init(void)
DST.size[0] = 0;
DST.size[1] = 0;
+ DST.inv_size[0] = 0;
+ DST.inv_size[1] = 0;
+
DST.default_framebuffer = NULL;
DST.vmempool = NULL;
}
- /* Refresh DST.screenvecs */
- copy_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]);
- copy_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]);
- normalize_v3(DST.screenvecs[0]);
- normalize_v3(DST.screenvecs[1]);
- /* Refresh DST.pixelsize */
- DST.pixsize = rv3d->pixsize;
+ if (rv3d != NULL) {
+ /* Refresh DST.screenvecs */
+ copy_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]);
+ copy_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]);
+ normalize_v3(DST.screenvecs[0]);
+ normalize_v3(DST.screenvecs[1]);
+
+ /* Refresh DST.pixelsize */
+ DST.pixsize = rv3d->pixsize;
+
+ copy_m4_m4(DST.original_mat.mat[DRW_MAT_PERS], rv3d->persmat);
+ copy_m4_m4(DST.original_mat.mat[DRW_MAT_PERSINV], rv3d->persinv);
+ copy_m4_m4(DST.original_mat.mat[DRW_MAT_VIEW], rv3d->viewmat);
+ copy_m4_m4(DST.original_mat.mat[DRW_MAT_VIEWINV], rv3d->viewinv);
+ copy_m4_m4(DST.original_mat.mat[DRW_MAT_WIN], rv3d->winmat);
+ invert_m4_m4(DST.original_mat.mat[DRW_MAT_WININV], rv3d->winmat);
+
+ memcpy(DST.view_data.matstate.mat, DST.original_mat.mat, sizeof(DST.original_mat.mat));
+
+ copy_v4_v4(DST.view_data.viewcamtexcofac, rv3d->viewcamtexcofac);
+ }
+ else {
+ copy_v4_fl4(DST.view_data.viewcamtexcofac, 1.0f, 1.0f, 0.0f, 0.0f);
+ }
/* Reset facing */
DST.frontface = GL_CCW;
DST.backface = GL_CW;
glFrontFace(DST.frontface);
- if (DST.draw_ctx.scene->obedit) {
- ED_view3d_init_mats_rv3d(DST.draw_ctx.scene->obedit, rv3d);
+ if (DST.draw_ctx.object_edit) {
+ ED_view3d_init_mats_rv3d(DST.draw_ctx.object_edit, rv3d);
}
/* Alloc array of texture reference. */
- if (RST.bound_texs == NULL) {
- RST.bound_texs = MEM_callocN(sizeof(GPUTexture *) * GPU_max_textures(), "Bound GPUTexture refs");
+ if (DST.RST.bound_texs == NULL) {
+ DST.RST.bound_texs = MEM_callocN(sizeof(GPUTexture *) * GPU_max_textures(), "Bound GPUTexture refs");
+ }
+ if (DST.RST.bound_tex_slots == NULL) {
+ DST.RST.bound_tex_slots = MEM_callocN(sizeof(char) * GPU_max_textures(), "Bound Texture Slots");
}
- if (RST.bound_tex_slots == NULL) {
- RST.bound_tex_slots = MEM_callocN(sizeof(bool) * GPU_max_textures(), "Bound Texture Slots");
+ if (DST.RST.bound_ubos == NULL) {
+ DST.RST.bound_ubos = MEM_callocN(sizeof(GPUUniformBuffer *) * GPU_max_ubo_binds(), "Bound GPUUniformBuffer refs");
}
+ if (DST.RST.bound_ubo_slots == NULL) {
+ DST.RST.bound_ubo_slots = MEM_callocN(sizeof(char) * GPU_max_ubo_binds(), "Bound Ubo Slots");
+ }
+
+ if (view_ubo == NULL) {
+ view_ubo = DRW_uniformbuffer_create(sizeof(ViewUboStorage), NULL);
+ }
+
+ DST.override_mat = 0;
+ DST.dirty_mat = true;
+ DST.state_cache_id = 1;
- memset(viewport_matrix_override.override, 0x0, sizeof(viewport_matrix_override.override));
+ DST.clipping.updated = false;
+
+ memset(DST.common_instance_data, 0x0, sizeof(DST.common_instance_data));
}
void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type)
{
- RegionView3D *rv3d = DST.draw_ctx.rv3d;
- BLI_assert(type >= DRW_MAT_PERS && type <= DRW_MAT_WININV);
+ BLI_assert(type >= 0 && type < DRW_MAT_COUNT);
+ BLI_assert(((DST.override_mat & (1 << type)) != 0)|| DST.draw_ctx.rv3d != NULL); /* Can't use this in render mode. */
- if (viewport_matrix_override.override[type]) {
- copy_m4_m4(mat, viewport_matrix_override.mat[type]);
- }
- else {
- switch (type) {
- case DRW_MAT_PERS:
- copy_m4_m4(mat, rv3d->persmat);
- break;
- case DRW_MAT_PERSINV:
- copy_m4_m4(mat, rv3d->persinv);
- break;
- case DRW_MAT_VIEW:
- copy_m4_m4(mat, rv3d->viewmat);
- break;
- case DRW_MAT_VIEWINV:
- copy_m4_m4(mat, rv3d->viewinv);
- break;
- case DRW_MAT_WIN:
- copy_m4_m4(mat, rv3d->winmat);
- break;
- case DRW_MAT_WININV:
- invert_m4_m4(mat, rv3d->winmat);
- break;
- default:
- BLI_assert(!"Matrix type invalid");
- break;
- }
- }
+ copy_m4_m4(mat, DST.view_data.matstate.mat[type]);
+}
+
+void DRW_viewport_matrix_get_all(DRWMatrixState *state)
+{
+ memcpy(state, DST.view_data.matstate.mat, sizeof(DRWMatrixState));
}
void DRW_viewport_matrix_override_set(float mat[4][4], DRWViewportMatrixType type)
{
- copy_m4_m4(viewport_matrix_override.mat[type], mat);
- viewport_matrix_override.override[type] = true;
+ BLI_assert(type < DRW_MAT_COUNT);
+ copy_m4_m4(DST.view_data.matstate.mat[type], mat);
+ DST.override_mat |= (1 << type);
+ DST.dirty_mat = true;
+ DST.clipping.updated = false;
}
void DRW_viewport_matrix_override_unset(DRWViewportMatrixType type)
{
- viewport_matrix_override.override[type] = false;
+ BLI_assert(type < DRW_MAT_COUNT);
+ copy_m4_m4(DST.view_data.matstate.mat[type], DST.original_mat.mat[type]);
+ DST.override_mat &= ~(1 << type);
+ DST.dirty_mat = true;
+ DST.clipping.updated = false;
+}
+
+void DRW_viewport_matrix_override_set_all(DRWMatrixState *state)
+{
+ memcpy(DST.view_data.matstate.mat, state, sizeof(DRWMatrixState));
+ DST.override_mat = 0xFFFFFF;
+ DST.dirty_mat = true;
+ DST.clipping.updated = false;
+}
+
+void DRW_viewport_matrix_override_unset_all(void)
+{
+ memcpy(DST.view_data.matstate.mat, DST.original_mat.mat, sizeof(DRWMatrixState));
+ DST.override_mat = 0;
+ DST.dirty_mat = true;
+ DST.clipping.updated = false;
}
bool DRW_viewport_is_persp_get(void)
{
RegionView3D *rv3d = DST.draw_ctx.rv3d;
- return rv3d->is_persp;
+ if (rv3d) {
+ return rv3d->is_persp;
+ }
+ else {
+ return DST.view_data.matstate.mat[DRW_MAT_WIN][3][3] == 0.0f;
+ }
+ BLI_assert(0);
+ return false;
}
DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void)
@@ -2765,51 +622,55 @@ void **DRW_view_layer_engine_data_ensure(DrawEngineType *engine_type, void (*cal
/** \name Objects (DRW_object)
* \{ */
-void *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type)
+ObjectEngineData *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type)
{
for (ObjectEngineData *oed = ob->drawdata.first; oed; oed = oed->next) {
if (oed->engine_type == engine_type) {
- return oed->storage;
+ return oed;
}
}
return NULL;
}
-void **DRW_object_engine_data_ensure(
- Object *ob, DrawEngineType *engine_type, void (*callback)(void *storage))
-{
- ObjectEngineData *oed;
-
- for (oed = ob->drawdata.first; oed; oed = oed->next) {
- if (oed->engine_type == engine_type) {
- return &oed->storage;
- }
+ObjectEngineData *DRW_object_engine_data_ensure(
+ Object *ob,
+ DrawEngineType *engine_type,
+ size_t size,
+ ObjectEngineDataInitCb init_cb,
+ ObjectEngineDataFreeCb free_cb)
+{
+ BLI_assert(size >= sizeof(ObjectEngineData));
+ /* Try to re-use existing data. */
+ ObjectEngineData *oed = DRW_object_engine_data_get(ob, engine_type);
+ if (oed != NULL) {
+ return oed;
+ }
+ /* Allocate new data. */
+ if ((ob->base_flag & BASE_FROMDUPLI) != 0) {
+ /* NOTE: data is not persistent in this case. It is reset each redraw. */
+ BLI_assert(free_cb == NULL); /* No callback allowed. */
+ /* Round to sizeof(float) for DRW_instance_data_request(). */
+ const size_t t = sizeof(float) - 1;
+ size = (size + t) & ~t;
+ size_t fsize = size / sizeof(float);
+ if (DST.common_instance_data[fsize] == NULL) {
+ DST.common_instance_data[fsize] = DRW_instance_data_request(DST.idatalist, fsize, 16);
+ }
+ oed = (ObjectEngineData *)DRW_instance_data_next(DST.common_instance_data[fsize]);
+ memset(oed, 0, size);
+ }
+ else {
+ oed = MEM_callocN(size, "ObjectEngineData");
}
-
- oed = MEM_callocN(sizeof(ObjectEngineData), "ObjectEngineData");
oed->engine_type = engine_type;
- oed->free = callback;
+ oed->free = free_cb;
+ /* Perform user-side initialization, if needed. */
+ if (init_cb != NULL) {
+ init_cb(oed);
+ }
+ /* Register in the list. */
BLI_addtail(&ob->drawdata, oed);
-
- return &oed->storage;
-}
-
-/* XXX There is definitly some overlap between this and DRW_object_engine_data_ensure.
- * We should get rid of one of the two. */
-LampEngineData *DRW_lamp_engine_data_ensure(Object *ob, RenderEngineType *engine_type)
-{
- BLI_assert(ob->type == OB_LAMP);
-
- Scene *scene = DST.draw_ctx.scene;
-
- /* TODO Dupliobjects */
- /* TODO Should be per scenelayer */
- return GPU_lamp_engine_data_get(scene, ob, NULL, engine_type);
-}
-
-void DRW_lamp_engine_data_free(LampEngineData *led)
-{
- GPU_lamp_engine_data_free(led);
+ return oed;
}
/** \} */
@@ -2824,7 +685,7 @@ static void drw_engines_init(void)
{
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
DrawEngineType *engine = link->data;
- ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+ ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
PROFILE_START(stime);
if (engine->engine_init) {
@@ -2839,7 +700,7 @@ static void drw_engines_cache_init(void)
{
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
DrawEngineType *engine = link->data;
- ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+ ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
if (data->text_draw_cache) {
DRW_text_cache_destroy(data->text_draw_cache);
@@ -2857,9 +718,15 @@ static void drw_engines_cache_init(void)
static void drw_engines_cache_populate(Object *ob)
{
+ DST.ob_state = NULL;
+
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
DrawEngineType *engine = link->data;
- ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+ ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
+
+ if (engine->id_update) {
+ engine->id_update(data, &ob->id);
+ }
if (engine->cache_populate) {
engine->cache_populate(data, ob);
@@ -2871,7 +738,7 @@ static void drw_engines_cache_finish(void)
{
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
DrawEngineType *engine = link->data;
- ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+ ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
if (engine->cache_finish) {
engine->cache_finish(data);
@@ -2883,7 +750,7 @@ static void drw_engines_draw_background(void)
{
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
DrawEngineType *engine = link->data;
- ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+ ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
if (engine->draw_background) {
PROFILE_START(stime);
@@ -2907,12 +774,16 @@ static void drw_engines_draw_scene(void)
{
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
DrawEngineType *engine = link->data;
- ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+ ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
PROFILE_START(stime);
if (engine->draw_scene) {
DRW_stats_group_start(engine->idname);
engine->draw_scene(data);
+ /* Restore for next engine */
+ if (DRW_state_is_fbo()) {
+ GPU_framebuffer_bind(DST.default_framebuffer);
+ }
DRW_stats_group_end();
}
@@ -2924,7 +795,7 @@ static void drw_engines_draw_text(void)
{
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
DrawEngineType *engine = link->data;
- ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+ ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
PROFILE_START(stime);
if (data->text_draw_cache) {
@@ -2945,7 +816,7 @@ int DRW_draw_region_engine_info_offset(void)
int lines = 0;
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
DrawEngineType *engine = link->data;
- ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+ ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
/* Count the number of lines. */
if (data->info[0] != '\0') {
@@ -2980,7 +851,7 @@ void DRW_draw_region_engine_info(void)
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
DrawEngineType *engine = link->data;
- ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+ ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
if (data->info[0] != '\0') {
char *chr_current = data->info;
@@ -3024,6 +895,14 @@ static void use_drw_engine(DrawEngineType *engine)
BLI_addtail(&DST.enabled_engines, ld);
}
+/**
+ * Use for external render engines.
+ */
+static void drw_engines_enable_external(void)
+{
+ use_drw_engine(DRW_engine_viewport_external_type.draw_engine);
+}
+
/* TODO revisit this when proper layering is implemented */
/* Gather all draw engines needed and store them in DST.enabled_engines
* That also define the rendering order of engines */
@@ -3106,18 +985,10 @@ static void drw_engines_enable_basic(void)
use_drw_engine(DRW_engine_viewport_basic_type.draw_engine);
}
-/**
- * Use for external render engines.
- */
-static void drw_engines_enable_external(void)
-{
- use_drw_engine(DRW_engine_viewport_external_type.draw_engine);
-}
-
-static void drw_engines_enable(const Scene *scene, ViewLayer *view_layer, RenderEngineType *engine_type)
+static void drw_engines_enable(ViewLayer *view_layer, RenderEngineType *engine_type)
{
Object *obact = OBACT(view_layer);
- const int mode = CTX_data_mode_enum_ex(scene->obedit, obact);
+ const int mode = CTX_data_mode_enum_ex(DST.draw_ctx.object_edit, obact, DST.draw_ctx.object_mode);
drw_engines_enable_from_engine(engine_type);
@@ -3145,127 +1016,6 @@ static unsigned int DRW_engines_get_hash(void)
return hash;
}
-static void draw_stat(rcti *rect, int u, int v, const char *txt, const int size)
-{
- BLF_draw_default_ascii(rect->xmin + (1 + u * 5) * U.widget_unit,
- rect->ymax - (3 + v) * U.widget_unit, 0.0f,
- txt, size);
-}
-
-/* CPU stats */
-static void drw_debug_cpu_stats(void)
-{
- int u, v;
- double init_tot_time = 0.0, background_tot_time = 0.0, render_tot_time = 0.0, tot_time = 0.0;
- /* local coordinate visible rect inside region, to accomodate overlapping ui */
- rcti rect;
- struct ARegion *ar = DST.draw_ctx.ar;
- ED_region_visible_rect(ar, &rect);
-
- UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
-
- /* row by row */
- v = 0; u = 0;
- /* Label row */
- char col_label[32];
- sprintf(col_label, "Engine");
- draw_stat(&rect, u++, v, col_label, sizeof(col_label));
- sprintf(col_label, "Init");
- draw_stat(&rect, u++, v, col_label, sizeof(col_label));
- sprintf(col_label, "Background");
- draw_stat(&rect, u++, v, col_label, sizeof(col_label));
- sprintf(col_label, "Render");
- draw_stat(&rect, u++, v, col_label, sizeof(col_label));
- sprintf(col_label, "Total (w/o cache)");
- draw_stat(&rect, u++, v, col_label, sizeof(col_label));
- v++;
-
- /* Engines rows */
- char time_to_txt[16];
- for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
- u = 0;
- DrawEngineType *engine = link->data;
- ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
-
- draw_stat(&rect, u++, v, engine->idname, sizeof(engine->idname));
-
- init_tot_time += data->init_time;
- sprintf(time_to_txt, "%.2fms", data->init_time);
- draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
-
- background_tot_time += data->background_time;
- sprintf(time_to_txt, "%.2fms", data->background_time);
- draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
-
- render_tot_time += data->render_time;
- sprintf(time_to_txt, "%.2fms", data->render_time);
- draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
-
- tot_time += data->init_time + data->background_time + data->render_time;
- sprintf(time_to_txt, "%.2fms", data->init_time + data->background_time + data->render_time);
- draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
- v++;
- }
-
- /* Totals row */
- u = 0;
- sprintf(col_label, "Sub Total");
- draw_stat(&rect, u++, v, col_label, sizeof(col_label));
- sprintf(time_to_txt, "%.2fms", init_tot_time);
- draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
- sprintf(time_to_txt, "%.2fms", background_tot_time);
- draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
- sprintf(time_to_txt, "%.2fms", render_tot_time);
- draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
- sprintf(time_to_txt, "%.2fms", tot_time);
- draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
- v += 2;
-
- u = 0;
- sprintf(col_label, "Cache Time");
- draw_stat(&rect, u++, v, col_label, sizeof(col_label));
- sprintf(time_to_txt, "%.2fms", DST.cache_time);
- draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
-}
-
-/* Display GPU time for each passes */
-static void drw_debug_gpu_stats(void)
-{
- /* local coordinate visible rect inside region, to accomodate overlapping ui */
- rcti rect;
- struct ARegion *ar = DST.draw_ctx.ar;
- ED_region_visible_rect(ar, &rect);
-
- UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
-
- int v = BLI_listbase_count(&DST.enabled_engines) + 5;
-
- char stat_string[32];
-
- /* Memory Stats */
- unsigned int tex_mem = GPU_texture_memory_usage_get();
- unsigned int vbo_mem = GWN_vertbuf_get_memory_usage();
-
- sprintf(stat_string, "GPU Memory");
- draw_stat(&rect, 0, v, stat_string, sizeof(stat_string));
- sprintf(stat_string, "%.2fMB", (double)(tex_mem + vbo_mem) / 1000000.0);
- draw_stat(&rect, 1, v++, stat_string, sizeof(stat_string));
- sprintf(stat_string, " |--> Textures");
- draw_stat(&rect, 0, v, stat_string, sizeof(stat_string));
- sprintf(stat_string, "%.2fMB", (double)tex_mem / 1000000.0);
- draw_stat(&rect, 1, v++, stat_string, sizeof(stat_string));
- sprintf(stat_string, " |--> Meshes");
- draw_stat(&rect, 0, v, stat_string, sizeof(stat_string));
- sprintf(stat_string, "%.2fMB", (double)vbo_mem / 1000000.0);
- draw_stat(&rect, 1, v++, stat_string, sizeof(stat_string));
-
- /* Pre offset for stats_draw */
- rect.ymax -= (3 + ++v) * U.widget_unit;
-
- /* Rendering Stats */
- DRW_stats_draw(&rect);
-}
-
/* -------------------------------------------------------------------- */
/** \name View Update
@@ -3285,21 +1035,27 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
return;
}
+ /* XXX Really nasty locking. But else this could
+ * be executed by the material previews thread
+ * while rendering a viewport. */
+ BLI_mutex_lock(&DST.ogl_context_mutex);
/* Reset before using it. */
- memset(&DST, 0x0, sizeof(DST));
+ drw_state_prepare_clean_for_draw(&DST);
DST.viewport = rv3d->viewport;
DST.draw_ctx = (DRWContextState){
- ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, depsgraph,
- NULL,
+ .ar = ar, .rv3d = rv3d, .v3d = v3d,
+ .scene = scene, .view_layer = view_layer, .obact = OBACT(view_layer),
+ .engine_type = engine_type,
+ .depsgraph = depsgraph, .object_mode = OB_MODE_OBJECT,
};
- drw_engines_enable(scene, view_layer, engine_type);
+ drw_engines_enable(view_layer, engine_type);
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
DrawEngineType *draw_engine = link->data;
- ViewportEngineData *data = DRW_viewport_engine_data_ensure(draw_engine);
+ ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine);
if (draw_engine->view_update) {
draw_engine->view_update(data);
@@ -3309,6 +1065,8 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
DST.viewport = NULL;
drw_engines_disable();
+
+ BLI_mutex_unlock(&DST.ogl_context_mutex);
}
/** \} */
@@ -3335,15 +1093,18 @@ void DRW_notify_id_update(const DRWUpdateContext *update_ctx, ID *id)
return;
}
/* Reset before using it. */
- memset(&DST, 0x0, sizeof(DST));
+ drw_state_prepare_clean_for_draw(&DST);
DST.viewport = rv3d->viewport;
DST.draw_ctx = (DRWContextState){
- ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, depsgraph, NULL,
+ .ar = ar, .rv3d = rv3d, .v3d = v3d,
+ .scene = scene, .view_layer = view_layer, .obact = OBACT(view_layer),
+ .engine_type = engine_type,
+ .depsgraph = depsgraph, .object_mode = OB_MODE_OBJECT,
};
- drw_engines_enable(scene, view_layer, engine_type);
+ drw_engines_enable(view_layer, engine_type);
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
DrawEngineType *draw_engine = link->data;
- ViewportEngineData *data = DRW_viewport_engine_data_ensure(draw_engine);
+ ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine);
if (draw_engine->id_update) {
draw_engine->id_update(data, id);
}
@@ -3364,14 +1125,15 @@ void DRW_notify_id_update(const DRWUpdateContext *update_ctx, ID *id)
* for each relevant engine / mode engine. */
void DRW_draw_view(const bContext *C)
{
- struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
RenderEngineType *engine_type = CTX_data_engine_type(C);
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
/* Reset before using it. */
- memset(&DST, 0x0, sizeof(DST));
- DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, C);
+ drw_state_prepare_clean_for_draw(&DST);
+ DRW_draw_render_loop_ex(eval_ctx.depsgraph, engine_type, ar, v3d, C);
}
/**
@@ -3384,6 +1146,7 @@ void DRW_draw_render_loop_ex(
ARegion *ar, View3D *v3d,
const bContext *evil_C)
{
+
Scene *scene = DEG_get_evaluated_scene(depsgraph);
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
RegionView3D *rv3d = ar->regiondata;
@@ -3397,42 +1160,54 @@ void DRW_draw_render_loop_ex(
GPU_viewport_engines_data_validate(DST.viewport, DRW_engines_get_hash());
DST.draw_ctx = (DRWContextState){
- ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, depsgraph,
+ .ar = ar, .rv3d = rv3d, .v3d = v3d,
+ .scene = scene, .view_layer = view_layer, .obact = OBACT(view_layer),
+ .engine_type = engine_type,
+ .depsgraph = depsgraph,
/* reuse if caller sets */
- DST.draw_ctx.evil_C,
+ .evil_C = DST.draw_ctx.evil_C,
};
-
+ drw_context_state_init();
drw_viewport_var_init();
/* Get list of enabled engines */
- drw_engines_enable(scene, view_layer, engine_type);
+ drw_engines_enable(view_layer, engine_type);
/* Update ubos */
DRW_globals_update();
+ /* No framebuffer allowed before drawing. */
+ BLI_assert(GPU_framebuffer_current_get() == 0);
+
/* Init engines */
drw_engines_init();
- /* TODO : tag to refresh by the dependency graph */
- /* ideally only refresh when objects are added/removed */
- /* or render properties / materials change */
+ /* Cache filling */
{
PROFILE_START(stime);
drw_engines_cache_init();
- DEG_OBJECT_ITER_FOR_RENDER_ENGINE(depsgraph, ob, DRW_iterator_mode_get())
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(depsgraph, ob, DRW_iterator_mode_get())
{
drw_engines_cache_populate(ob);
}
- DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
drw_engines_cache_finish();
- PROFILE_END_ACCUM(DST.cache_time, stime);
+
+ DRW_render_instance_buffer_finish();
+
+#ifdef USE_PROFILE
+ double *cache_time = GPU_viewport_cache_time_get(DST.viewport);
+ PROFILE_END_UPDATE(*cache_time, stime);
+#endif
}
DRW_stats_begin();
+ GPU_framebuffer_bind(DST.default_framebuffer);
+
/* Start Drawing */
DRW_state_reset();
@@ -3491,10 +1266,15 @@ void DRW_draw_render_loop_ex(
}
if (G.debug_value > 20) {
- drw_debug_cpu_stats();
- drw_debug_gpu_stats();
+ glDisable(GL_DEPTH_TEST);
+ rcti rect; /* local coordinate visible rect inside region, to accomodate overlapping ui */
+ ED_region_visible_rect(DST.draw_ctx.ar, &rect);
+ DRW_stats_draw(&rect);
+ glEnable(GL_DEPTH_TEST);
}
+ GPU_framebuffer_restore();
+
DRW_state_reset();
drw_engines_disable();
@@ -3502,7 +1282,7 @@ void DRW_draw_render_loop_ex(
#ifdef DEBUG
/* Avoid accidental reuse. */
- memset(&DST, 0xFF, sizeof(DST));
+ drw_state_ensure_not_reused(&DST);
#endif
}
@@ -3511,7 +1291,7 @@ void DRW_draw_render_loop(
ARegion *ar, View3D *v3d)
{
/* Reset before using it. */
- memset(&DST, 0x0, sizeof(DST));
+ drw_state_prepare_clean_for_draw(&DST);
Scene *scene = DEG_get_evaluated_scene(depsgraph);
RenderEngineType *engine_type = RE_engines_find(scene->view_render.engine_id);
@@ -3522,7 +1302,8 @@ void DRW_draw_render_loop(
/* @viewport CAN be NULL, in this case we create one. */
void DRW_draw_render_loop_offscreen(
struct Depsgraph *depsgraph, RenderEngineType *engine_type,
- ARegion *ar, View3D *v3d, const bool draw_background, GPUOffScreen *ofs,
+ ARegion *ar, View3D *v3d,
+ const bool draw_background, GPUOffScreen *ofs,
GPUViewport *viewport)
{
RegionView3D *rv3d = ar->regiondata;
@@ -3539,8 +1320,10 @@ void DRW_draw_render_loop_offscreen(
}
}
+ GPU_framebuffer_restore();
+
/* Reset before using it. */
- memset(&DST, 0x0, sizeof(DST));
+ drw_state_prepare_clean_for_draw(&DST);
DST.options.is_image_render = true;
DST.options.draw_background = draw_background;
DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, NULL);
@@ -3551,7 +1334,6 @@ void DRW_draw_render_loop_offscreen(
/* don't free data owned by 'ofs' */
GPU_viewport_clear_from_offscreen(rv3d->viewport);
GPU_viewport_free(rv3d->viewport);
- MEM_freeN(rv3d->viewport);
}
rv3d->viewport = backup_viewport;
@@ -3561,24 +1343,163 @@ void DRW_draw_render_loop_offscreen(
GPU_offscreen_bind(ofs, false);
}
+void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
+{
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
+ RenderEngineType *engine_type = engine->type;
+ DrawEngineType *draw_engine_type = engine_type->draw_engine;
+ RenderData *r = &scene->r;
+ Render *render = engine->re;
+ /* Changing Context */
+ DRW_opengl_context_enable();
+ /* IMPORTANT: We dont support immediate mode in render mode!
+ * This shall remain in effect until immediate mode supports
+ * multiple threads. */
+
+ /* Reset before using it. */
+ drw_state_prepare_clean_for_draw(&DST);
+ DST.options.is_image_render = true;
+ DST.options.is_scene_render = true;
+ DST.options.draw_background = scene->r.alphamode == R_ADDSKY;
+
+ DST.draw_ctx = (DRWContextState){
+ .scene = scene, .view_layer = view_layer,
+ .engine_type = engine_type,
+ .depsgraph = depsgraph, .object_mode = OB_MODE_OBJECT,
+ };
+ drw_context_state_init();
+
+ DST.viewport = GPU_viewport_create();
+ const int size[2] = {(r->size * r->xsch) / 100, (r->size * r->ysch) / 100};
+ GPU_viewport_size_set(DST.viewport, size);
+
+ drw_viewport_var_init();
+
+ ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine_type);
+
+ /* set default viewport */
+ glViewport(0, 0, size[0], size[1]);
+
+ /* Main rendering. */
+ rctf view_rect;
+ rcti render_rect;
+ RE_GetViewPlane(render, &view_rect, &render_rect);
+ if (BLI_rcti_is_empty(&render_rect)) {
+ BLI_rcti_init(&render_rect, 0, size[0], 0, size[1]);
+ }
+
+ /* Init render result. */
+ RenderResult *render_result = RE_engine_begin_result(
+ engine,
+ 0,
+ 0,
+ (int)size[0],
+ (int)size[1],
+ view_layer->name,
+ /* RR_ALL_VIEWS */ NULL);
+
+ RenderLayer *render_layer = render_result->layers.first;
+ for (RenderView *render_view = render_result->views.first;
+ render_view != NULL;
+ render_view = render_view->next)
+ {
+ RE_SetActiveRenderView(render, render_view->name);
+ engine_type->draw_engine->render_to_image(data, engine, render_layer, &render_rect);
+ DST.buffer_finish_called = false;
+ }
+
+ RE_engine_end_result(engine, render_result, false, false, false);
+
+ /* Force cache to reset. */
+ drw_viewport_cache_resize();
+
+ /* TODO grease pencil */
+
+ GPU_viewport_free(DST.viewport);
+ GPU_framebuffer_restore();
+
+ /* Changing Context */
+ DRW_opengl_context_disable();
+
+#ifdef DEBUG
+ /* Avoid accidental reuse. */
+ drw_state_ensure_not_reused(&DST);
+#endif
+}
+
+void DRW_render_object_iter(
+ void *vedata, RenderEngine *engine, struct Depsgraph *depsgraph,
+ void (*callback)(void *vedata, Object *ob, RenderEngine *engine, struct Depsgraph *depsgraph))
+{
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(depsgraph, ob, DRW_iterator_mode_get())
+ {
+ DST.ob_state = NULL;
+ callback(vedata, ob, engine, depsgraph);
+ }
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END
+}
+
+static struct DRWSelectBuffer {
+ struct GPUFrameBuffer *framebuffer;
+ struct GPUTexture *texture_depth;
+} g_select_buffer = {NULL};
+
+static void draw_select_framebuffer_setup(const rcti *rect)
+{
+ if (g_select_buffer.framebuffer == NULL) {
+ g_select_buffer.framebuffer = GPU_framebuffer_create();
+ }
+
+ /* If size mismatch recreate the texture. */
+ if ((g_select_buffer.texture_depth != NULL) &&
+ ((GPU_texture_width(g_select_buffer.texture_depth) != BLI_rcti_size_x(rect)) ||
+ (GPU_texture_height(g_select_buffer.texture_depth) != BLI_rcti_size_y(rect))))
+ {
+ GPU_texture_free(g_select_buffer.texture_depth);
+ g_select_buffer.texture_depth = NULL;
+ }
+
+ if (g_select_buffer.texture_depth == NULL) {
+ g_select_buffer.texture_depth = GPU_texture_create_depth(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), NULL);
+
+ GPU_framebuffer_texture_attach(g_select_buffer.framebuffer, g_select_buffer.texture_depth, 0, 0);
+
+ if (!GPU_framebuffer_check_valid(g_select_buffer.framebuffer, NULL)) {
+ printf("Error invalid selection framebuffer\n");
+ }
+ }
+}
+
+/* Must run after all instance datas have been added. */
+void DRW_render_instance_buffer_finish(void)
+{
+ BLI_assert(!DST.buffer_finish_called && "DRW_render_instance_buffer_finish called twice!");
+ DST.buffer_finish_called = true;
+ DRW_instance_buffer_finish(DST.idatalist);
+}
+
/**
* object mode select-loop, see: ED_view3d_draw_select_loop (legacy drawing).
*/
void DRW_draw_select_loop(
struct Depsgraph *depsgraph,
ARegion *ar, View3D *v3d,
- bool UNUSED(use_obedit_skip), bool UNUSED(use_nearest), const rcti *rect)
+ bool UNUSED(use_obedit_skip), bool UNUSED(use_nearest), const rcti *rect,
+ DRW_SelectPassFn select_pass_fn, void *select_pass_user_data)
{
Scene *scene = DEG_get_evaluated_scene(depsgraph);
RenderEngineType *engine_type = RE_engines_find(scene->view_render.engine_id);
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
+ Object *obact = OBACT(view_layer);
+ Object *obedit = OBEDIT_FROM_OBACT(obact);
#ifndef USE_GPU_SELECT
UNUSED_VARS(vc, scene, view_layer, v3d, ar, rect);
#else
RegionView3D *rv3d = ar->regiondata;
/* Reset before using it. */
- memset(&DST, 0x0, sizeof(DST));
+ drw_state_prepare_clean_for_draw(&DST);
/* backup (_never_ use rv3d->viewport) */
void *backup_viewport = rv3d->viewport;
@@ -3586,14 +1507,12 @@ void DRW_draw_select_loop(
bool use_obedit = false;
int obedit_mode = 0;
- if (scene->obedit && scene->obedit->type == OB_MBALL) {
- use_obedit = true;
- obedit_mode = CTX_MODE_EDIT_METABALL;
- }
- else if ((scene->obedit && scene->obedit->type == OB_ARMATURE)) {
- /* if not drawing sketch, draw bones */
- // if (!BDR_drawSketchNames(vc))
- {
+ if (obedit != NULL) {
+ if (obedit->type == OB_MBALL) {
+ use_obedit = true;
+ obedit_mode = CTX_MODE_EDIT_METABALL;
+ }
+ else if (obedit->type == OB_ARMATURE) {
use_obedit = true;
obedit_mode = CTX_MODE_EDIT_ARMATURE;
}
@@ -3602,7 +1521,6 @@ void DRW_draw_select_loop(
struct GPUViewport *viewport = GPU_viewport_create();
GPU_viewport_size_set(viewport, (const int[2]){BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)});
- bool cache_is_dirty;
DST.viewport = viewport;
v3d->zbuf = true;
@@ -3618,13 +1536,15 @@ void DRW_draw_select_loop(
}
/* Setup viewport */
- cache_is_dirty = true;
/* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
DST.draw_ctx = (DRWContextState){
- ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, depsgraph, (bContext *)NULL,
+ .ar = ar, .rv3d = rv3d, .v3d = v3d,
+ .scene = scene, .view_layer = view_layer, .obact = obact,
+ .engine_type = engine_type,
+ .depsgraph = depsgraph,
};
-
+ drw_context_state_init();
drw_viewport_var_init();
/* Update ubos */
@@ -3633,36 +1553,64 @@ void DRW_draw_select_loop(
/* Init engines */
drw_engines_init();
- /* TODO : tag to refresh by the dependency graph */
- /* ideally only refresh when objects are added/removed */
- /* or render properties / materials change */
- if (cache_is_dirty) {
+ {
drw_engines_cache_init();
if (use_obedit) {
- drw_engines_cache_populate(scene->obedit);
+ drw_engines_cache_populate(obact);
}
else {
- DEG_OBJECT_ITER(depsgraph, ob, DRW_iterator_mode_get(),
- DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
- DEG_ITER_OBJECT_FLAG_VISIBLE |
- DEG_ITER_OBJECT_FLAG_DUPLI)
+ DEG_OBJECT_ITER_BEGIN(
+ depsgraph, ob, DRW_iterator_mode_get(),
+ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
+ DEG_ITER_OBJECT_FLAG_VISIBLE |
+ DEG_ITER_OBJECT_FLAG_DUPLI)
{
if ((ob->base_flag & BASE_SELECTABLED) != 0) {
DRW_select_load_id(ob->select_color);
drw_engines_cache_populate(ob);
}
}
- DEG_OBJECT_ITER_END
+ DEG_OBJECT_ITER_END;
}
drw_engines_cache_finish();
+
+ DRW_render_instance_buffer_finish();
}
+ /* Setup framebuffer */
+ draw_select_framebuffer_setup(rect);
+ GPU_framebuffer_bind(g_select_buffer.framebuffer);
+ GPU_framebuffer_clear_depth(g_select_buffer.framebuffer, 1.0f);
+
/* Start Drawing */
DRW_state_reset();
DRW_draw_callbacks_pre_scene();
- drw_engines_draw_scene();
+
+ DRW_state_lock(
+ DRW_STATE_WRITE_DEPTH |
+ DRW_STATE_DEPTH_ALWAYS |
+ DRW_STATE_DEPTH_LESS |
+ DRW_STATE_DEPTH_EQUAL |
+ DRW_STATE_DEPTH_GREATER |
+ DRW_STATE_DEPTH_ALWAYS);
+
+ /* Only 1-2 passes. */
+ while (true) {
+ if (!select_pass_fn(DRW_SELECT_PASS_PRE, select_pass_user_data)) {
+ break;
+ }
+
+ drw_engines_draw_scene();
+
+ if (!select_pass_fn(DRW_SELECT_PASS_POST, select_pass_user_data)) {
+ break;
+ }
+ }
+
+ DRW_state_lock(0);
+
DRW_draw_callbacks_post_scene();
DRW_state_reset();
@@ -3670,18 +1618,54 @@ void DRW_draw_select_loop(
#ifdef DEBUG
/* Avoid accidental reuse. */
- memset(&DST, 0xFF, sizeof(DST));
+ drw_state_ensure_not_reused(&DST);
#endif
+ GPU_framebuffer_restore();
/* Cleanup for selection state */
GPU_viewport_free(viewport);
- MEM_freeN(viewport);
/* restore */
rv3d->viewport = backup_viewport;
#endif /* USE_GPU_SELECT */
}
+static void draw_depth_texture_to_screen(GPUTexture *texture)
+{
+ const float w = (float)GPU_texture_width(texture);
+ const float h = (float)GPU_texture_height(texture);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_DEPTH_COPY);
+
+ GPU_texture_bind(texture, 0);
+
+ immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
+
+ immBegin(GWN_PRIM_TRI_STRIP, 4);
+
+ immAttrib2f(texcoord, 0.0f, 0.0f);
+ immVertex2f(pos, 0.0f, 0.0f);
+
+ immAttrib2f(texcoord, 1.0f, 0.0f);
+ immVertex2f(pos, w, 0.0f);
+
+ immAttrib2f(texcoord, 0.0f, 1.0f);
+ immVertex2f(pos, 0.0f, h);
+
+ immAttrib2f(texcoord, 1.0f, 1.0f);
+ immVertex2f(pos, w, h);
+
+ immEnd();
+
+ GPU_texture_unbind(texture);
+
+ immUnbindProgram();
+}
+
/**
* object mode select-loop, see: ED_view3d_draw_depth_loop (legacy drawing).
*/
@@ -3694,16 +1678,23 @@ void DRW_draw_depth_loop(
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
RegionView3D *rv3d = ar->regiondata;
+ DRW_opengl_context_enable();
+
/* backup (_never_ use rv3d->viewport) */
void *backup_viewport = rv3d->viewport;
rv3d->viewport = NULL;
/* Reset before using it. */
- memset(&DST, 0x0, sizeof(DST));
+ drw_state_prepare_clean_for_draw(&DST);
struct GPUViewport *viewport = GPU_viewport_create();
GPU_viewport_size_set(viewport, (const int[2]){ar->winx, ar->winy});
+ /* Setup framebuffer */
+ draw_select_framebuffer_setup(&ar->winrct);
+ GPU_framebuffer_bind(g_select_buffer.framebuffer);
+ GPU_framebuffer_clear_depth(g_select_buffer.framebuffer, 1.0f);
+
bool cache_is_dirty;
DST.viewport = viewport;
v3d->zbuf = true;
@@ -3721,9 +1712,12 @@ void DRW_draw_depth_loop(
/* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
DST.draw_ctx = (DRWContextState){
- ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, depsgraph, (bContext *)NULL,
+ .ar = ar, .rv3d = rv3d, .v3d = v3d,
+ .scene = scene, .view_layer = view_layer, .obact = OBACT(view_layer),
+ .engine_type = engine_type,
+ .depsgraph = depsgraph,
};
-
+ drw_context_state_init();
drw_viewport_var_init();
/* Update ubos */
@@ -3738,13 +1732,15 @@ void DRW_draw_depth_loop(
if (cache_is_dirty) {
drw_engines_cache_init();
- DEG_OBJECT_ITER_FOR_RENDER_ENGINE(depsgraph, ob, DRW_iterator_mode_get())
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(depsgraph, ob, DRW_iterator_mode_get())
{
drw_engines_cache_populate(ob);
}
- DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
drw_engines_cache_finish();
+
+ DRW_render_instance_buffer_finish();
}
/* Start Drawing */
@@ -3758,12 +1754,32 @@ void DRW_draw_depth_loop(
#ifdef DEBUG
/* Avoid accidental reuse. */
- memset(&DST, 0xFF, sizeof(DST));
+ drw_state_ensure_not_reused(&DST);
#endif
+ /* TODO: Reading depth for operators should be done here. */
+
+ GPU_framebuffer_restore();
+
/* Cleanup for selection state */
GPU_viewport_free(viewport);
- MEM_freeN(viewport);
+
+ /* Changin context */
+ DRW_opengl_context_disable();
+
+ /* XXX Drawing the resulting buffer to the BACK_BUFFER */
+ gpuPushMatrix();
+ gpuPushProjectionMatrix();
+ wmOrtho2_region_pixelspace(ar);
+ gpuLoadIdentity();
+
+ glEnable(GL_DEPTH_TEST); /* Cannot write to depth buffer without testing */
+ glDepthFunc(GL_ALWAYS);
+ draw_depth_texture_to_screen(g_select_buffer.texture_depth);
+ glDepthFunc(GL_LEQUAL);
+
+ gpuPopMatrix();
+ gpuPopProjectionMatrix();
/* restore */
rv3d->viewport = backup_viewport;
@@ -3788,7 +1804,7 @@ void DRW_state_dfdy_factors_get(float dfdyfac[2])
*/
bool DRW_state_is_fbo(void)
{
- return (DST.default_framebuffer != NULL);
+ return ((DST.default_framebuffer != NULL) || DST.options.is_image_render);
}
/**
@@ -3824,6 +1840,14 @@ bool DRW_state_is_scene_render(void)
}
/**
+* Whether we are rendering simple opengl render
+*/
+bool DRW_state_is_opengl_render(void)
+{
+ return DST.options.is_image_render && !DST.options.is_scene_render;
+}
+
+/**
* Gives you the iterator mode to use for depsgraph.
*/
eDepsObjectIteratorMode DRW_iterator_mode_get(void)
@@ -3886,6 +1910,11 @@ const DRWContextState *DRW_context_state_get(void)
/** \name Init/Exit (DRW_engines)
* \{ */
+bool DRW_engine_render_support(DrawEngineType *draw_engine_type)
+{
+ return draw_engine_type->render_to_image;
+}
+
void DRW_engine_register(DrawEngineType *draw_engine_type)
{
BLI_addtail(&DRW_engines, draw_engine_type);
@@ -3961,12 +1990,19 @@ void DRW_engines_register(void)
}
}
+extern struct Gwn_VertFormat *g_pos_format; /* draw_shgroup.c */
extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
extern struct GPUTexture *globals_ramp; /* draw_common.c */
void DRW_engines_free(void)
{
+ DRW_opengl_context_enable();
+
+ DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_depth);
+ GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer);
+
DRW_shape_cache_free();
DRW_stats_free();
+ DRW_globals_free();
DrawEngineType *next;
for (DrawEngineType *type = DRW_engines.first; type; type = next) {
@@ -3978,14 +2014,17 @@ void DRW_engines_free(void)
}
}
- if (globals_ubo)
- GPU_uniformbuffer_free(globals_ubo);
+ DRW_UBO_FREE_SAFE(globals_ubo);
+ DRW_UBO_FREE_SAFE(view_ubo);
+ DRW_TEXTURE_FREE_SAFE(globals_ramp);
+ MEM_SAFE_FREE(g_pos_format);
- if (globals_ramp)
- GPU_texture_free(globals_ramp);
+ MEM_SAFE_FREE(DST.RST.bound_texs);
+ MEM_SAFE_FREE(DST.RST.bound_tex_slots);
+ MEM_SAFE_FREE(DST.RST.bound_ubos);
+ MEM_SAFE_FREE(DST.RST.bound_ubo_slots);
- MEM_SAFE_FREE(RST.bound_texs);
- MEM_SAFE_FREE(RST.bound_tex_slots);
+ DRW_opengl_context_disable();
#ifdef WITH_CLAY_ENGINE
BLI_remlink(&R_engines, &DRW_engine_viewport_clay_type);
@@ -3993,3 +2032,78 @@ void DRW_engines_free(void)
}
/** \} */
+
+/** \name Init/Exit (DRW_opengl_ctx)
+ * \{ */
+
+void DRW_opengl_context_create(void)
+{
+ BLI_assert(DST.ogl_context == NULL); /* Ensure it's called once */
+
+ BLI_mutex_init(&DST.ogl_context_mutex);
+
+ immDeactivate();
+ /* This changes the active context. */
+ DST.ogl_context = WM_opengl_context_create();
+ /* Be sure to create gawain.context too. */
+ DST.gwn_context = GWN_context_create();
+ immActivate();
+ /* Set default Blender OpenGL state */
+ GPU_state_init();
+ /* So we activate the window's one afterwards. */
+ wm_window_reset_drawable();
+}
+
+void DRW_opengl_context_destroy(void)
+{
+ BLI_assert(BLI_thread_is_main());
+ if (DST.ogl_context != NULL) {
+ WM_opengl_context_activate(DST.ogl_context);
+ GWN_context_active_set(DST.gwn_context);
+ GWN_context_discard(DST.gwn_context);
+ WM_opengl_context_dispose(DST.ogl_context);
+ BLI_mutex_end(&DST.ogl_context_mutex);
+ }
+}
+
+void DRW_opengl_context_enable(void)
+{
+ if (DST.ogl_context != NULL) {
+ /* IMPORTANT: We dont support immediate mode in render mode!
+ * This shall remain in effect until immediate mode supports
+ * multiple threads. */
+ BLI_mutex_lock(&DST.ogl_context_mutex);
+ if (BLI_thread_is_main()) {
+ immDeactivate();
+ }
+ WM_opengl_context_activate(DST.ogl_context);
+ GWN_context_active_set(DST.gwn_context);
+ if (BLI_thread_is_main()) {
+ immActivate();
+ BLF_batch_reset();
+ }
+ }
+}
+
+void DRW_opengl_context_disable(void)
+{
+ if (DST.ogl_context != NULL) {
+#ifdef __APPLE__
+ /* Need to flush before disabling draw context, otherwise it does not
+ * always finish drawing and viewport can be empty or partially drawn */
+ glFlush();
+#endif
+
+ if (BLI_thread_is_main()) {
+ wm_window_reset_drawable();
+ }
+ else {
+ WM_opengl_context_release(DST.ogl_context);
+ GWN_context_active_set(NULL);
+ }
+
+ BLI_mutex_unlock(&DST.ogl_context_mutex);
+ }
+}
+
+/** \} */
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
new file mode 100644
index 00000000000..dd7e84f67d4
--- /dev/null
+++ b/source/blender/draw/intern/draw_manager.h
@@ -0,0 +1,358 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file draw_manager.h
+ * \ingroup draw
+ */
+
+/* Private functions / structs of the draw manager */
+
+#ifndef __DRAW_MANAGER_H__
+#define __DRAW_MANAGER_H__
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "BLI_linklist.h"
+#include "BLI_threads.h"
+
+#include "GPU_batch.h"
+#include "GPU_framebuffer.h"
+#include "GPU_shader.h"
+#include "GPU_uniformbuffer.h"
+#include "GPU_viewport.h"
+
+#include "draw_instance_data.h"
+
+/* Use draw manager to call GPU_select, see: DRW_draw_select_loop */
+#define USE_GPU_SELECT
+
+/* ------------ Profiling --------------- */
+
+#define USE_PROFILE
+
+#ifdef USE_PROFILE
+# include "PIL_time.h"
+
+# define PROFILE_TIMER_FALLOFF 0.04
+
+# define PROFILE_START(time_start) \
+ double time_start = PIL_check_seconds_timer();
+
+# define PROFILE_END_ACCUM(time_accum, time_start) { \
+ time_accum += (PIL_check_seconds_timer() - time_start) * 1e3; \
+} ((void)0)
+
+/* exp average */
+# define PROFILE_END_UPDATE(time_update, time_start) { \
+ double _time_delta = (PIL_check_seconds_timer() - time_start) * 1e3; \
+ time_update = (time_update * (1.0 - PROFILE_TIMER_FALLOFF)) + \
+ (_time_delta * PROFILE_TIMER_FALLOFF); \
+} ((void)0)
+
+#else /* USE_PROFILE */
+
+# define PROFILE_START(time_start) ((void)0)
+# define PROFILE_END_ACCUM(time_accum, time_start) ((void)0)
+# define PROFILE_END_UPDATE(time_update, time_start) ((void)0)
+
+#endif /* USE_PROFILE */
+
+/* ------------ Data Structure --------------- */
+/**
+ * Data structure containing all drawcalls organized by passes and materials.
+ * DRWPass > DRWShadingGroup > DRWCall > DRWCallState
+ * > DRWUniform
+ **/
+
+/* Used by DRWCallState.flag */
+enum {
+ DRW_CALL_CULLED = (1 << 0),
+ DRW_CALL_NEGSCALE = (1 << 1),
+};
+
+/* Used by DRWCallState.matflag */
+enum {
+ DRW_CALL_MODELINVERSE = (1 << 0),
+ DRW_CALL_MODELVIEW = (1 << 1),
+ DRW_CALL_MODELVIEWINVERSE = (1 << 2),
+ DRW_CALL_MODELVIEWPROJECTION = (1 << 3),
+ DRW_CALL_NORMALVIEW = (1 << 4),
+ DRW_CALL_NORMALWORLD = (1 << 5),
+ DRW_CALL_ORCOTEXFAC = (1 << 6),
+ DRW_CALL_EYEVEC = (1 << 7),
+};
+
+typedef struct DRWCallState {
+ unsigned char flag;
+ unsigned char cache_id; /* Compared with DST.state_cache_id to see if matrices are still valid. */
+ uint16_t matflag; /* Which matrices to compute. */
+ /* Culling: Using Bounding Sphere for now for faster culling.
+ * Not ideal for planes. */
+ BoundSphere bsphere;
+ /* Matrices */
+ float model[4][4];
+ float modelinverse[4][4];
+ float modelview[4][4];
+ float modelviewinverse[4][4];
+ float modelviewprojection[4][4];
+ float normalview[3][3];
+ float normalworld[3][3]; /* Not view dependant */
+ float orcotexfac[2][3]; /* Not view dependant */
+ float eyevec[3];
+} DRWCallState;
+
+typedef enum {
+ DRW_CALL_SINGLE, /* A single batch */
+ DRW_CALL_INSTANCES, /* Draw instances without any instancing attribs. */
+ DRW_CALL_GENERATE, /* Uses a callback to draw with any number of batches. */
+} DRWCallType;
+
+typedef struct DRWCall {
+ struct DRWCall *next;
+ DRWCallState *state;
+
+ union {
+ struct { /* type == DRW_CALL_SINGLE */
+ Gwn_Batch *geometry;
+ } single;
+ struct { /* type == DRW_CALL_INSTANCES */
+ Gwn_Batch *geometry;
+ /* Count can be adjusted between redraw. If needed, we can add fixed count. */
+ unsigned int *count;
+ } instances;
+ struct { /* type == DRW_CALL_GENERATE */
+ DRWCallGenerateFn *geometry_fn;
+ void *user_data;
+ } generate;
+ };
+
+ DRWCallType type;
+#ifdef USE_GPU_SELECT
+ int select_id;
+#endif
+} DRWCall;
+
+/* Used by DRWUniform.type */
+typedef enum {
+ DRW_UNIFORM_BOOL,
+ DRW_UNIFORM_SHORT_TO_INT,
+ DRW_UNIFORM_SHORT_TO_FLOAT,
+ DRW_UNIFORM_INT,
+ DRW_UNIFORM_FLOAT,
+ DRW_UNIFORM_TEXTURE,
+ DRW_UNIFORM_TEXTURE_PERSIST,
+ DRW_UNIFORM_TEXTURE_REF,
+ DRW_UNIFORM_BLOCK,
+ DRW_UNIFORM_BLOCK_PERSIST
+} DRWUniformType;
+
+struct DRWUniform {
+ DRWUniform *next; /* single-linked list */
+ const void *value;
+ int location;
+ char type; /* DRWUniformType */
+ char length; /* cannot be more than 16 */
+ char arraysize; /* cannot be more than 16 too */
+};
+
+typedef enum {
+ DRW_SHG_NORMAL,
+ DRW_SHG_POINT_BATCH,
+ DRW_SHG_LINE_BATCH,
+ DRW_SHG_TRIANGLE_BATCH,
+ DRW_SHG_INSTANCE,
+ DRW_SHG_INSTANCE_EXTERNAL,
+} DRWShadingGroupType;
+
+struct DRWShadingGroup {
+ DRWShadingGroup *next;
+
+ GPUShader *shader; /* Shader to bind */
+ DRWUniform *uniforms; /* Uniforms pointers */
+
+ /* Watch this! Can be nasty for debugging. */
+ union {
+ struct { /* DRW_SHG_NORMAL */
+ DRWCall *first, *last; /* Linked list of DRWCall or DRWCallDynamic depending of type */
+ } calls;
+ struct { /* DRW_SHG_***_BATCH */
+ struct Gwn_Batch *batch_geom; /* Result of call batching */
+ struct Gwn_VertBuf *batch_vbo;
+ unsigned int primitive_count;
+ };
+ struct { /* DRW_SHG_INSTANCE[_EXTERNAL] */
+ struct Gwn_Batch *instance_geom;
+ struct Gwn_VertBuf *instance_vbo;
+ unsigned int instance_count;
+ float instance_orcofac[2][3]; /* TODO find a better place. */
+ };
+ };
+
+ DRWState state_extra; /* State changes for this batch only (or'd with the pass's state) */
+ DRWState state_extra_disable; /* State changes for this batch only (and'd with the pass's state) */
+ unsigned int stencil_mask; /* Stencil mask to use for stencil test / write operations */
+ DRWShadingGroupType type;
+
+ /* Builtin matrices locations */
+ int model;
+ int modelinverse;
+ int modelview;
+ int modelviewinverse;
+ int modelviewprojection;
+ int normalview;
+ int normalworld;
+ int orcotexfac;
+ int eye;
+ uint16_t matflag; /* Matrices needed, same as DRWCall.flag */
+
+#ifndef NDEBUG
+ char attribs_count;
+#endif
+
+#ifdef USE_GPU_SELECT
+ DRWInstanceData *inst_selectid;
+ DRWPass *pass_parent; /* backlink to pass we're in */
+ int override_selectid; /* Override for single object instances. */
+#endif
+};
+
+#define MAX_PASS_NAME 32
+
+struct DRWPass {
+ /* Linked list */
+ struct {
+ DRWShadingGroup *first;
+ DRWShadingGroup *last;
+ } shgroups;
+
+ DRWState state;
+ char name[MAX_PASS_NAME];
+};
+
+typedef struct ViewUboStorage {
+ DRWMatrixState matstate;
+ float viewcamtexcofac[4];
+ float clipplanes[2][4];
+} ViewUboStorage;
+
+/* ------------- DRAW MANAGER ------------ */
+
+#define MAX_CLIP_PLANES 6 /* GL_MAX_CLIP_PLANES is at least 6 */
+
+typedef struct DRWManager {
+ /* TODO clean up this struct a bit */
+ /* Cache generation */
+ ViewportMemoryPool *vmempool;
+ DRWInstanceDataList *idatalist;
+ DRWInstanceData *common_instance_data[MAX_INSTANCE_DATA_SIZE];
+ /* State of the object being evaluated if already allocated. */
+ DRWCallState *ob_state;
+ unsigned char state_cache_id; /* Could be larger but 254 view changes is already a lot! */
+
+ /* Rendering state */
+ GPUShader *shader;
+
+ /* Managed by `DRW_state_set`, `DRW_state_reset` */
+ DRWState state;
+ DRWState state_lock;
+ unsigned int stencil_mask;
+
+ /* Per viewport */
+ GPUViewport *viewport;
+ struct GPUFrameBuffer *default_framebuffer;
+ float size[2];
+ float inv_size[2];
+ float screenvecs[2][3];
+ float pixsize;
+
+ GLenum backface, frontface;
+
+ struct {
+ unsigned int is_select : 1;
+ unsigned int is_depth : 1;
+ unsigned int is_image_render : 1;
+ unsigned int is_scene_render : 1;
+ unsigned int draw_background : 1;
+ } options;
+
+ /* Current rendering context */
+ DRWContextState draw_ctx;
+
+ /* Convenience pointer to text_store owned by the viewport */
+ struct DRWTextStore **text_store_p;
+
+ ListBase enabled_engines; /* RenderEngineType */
+
+ bool buffer_finish_called; /* Avoid bad usage of DRW_render_instance_buffer_finish */
+
+ /* View dependant uniforms. */
+ DRWMatrixState original_mat; /* Original rv3d matrices. */
+ int override_mat; /* Bitflag of which matrices are overriden. */
+ int num_clip_planes; /* Number of active clipplanes. */
+ bool dirty_mat;
+
+ /* keep in sync with viewBlock */
+ ViewUboStorage view_data;
+
+ struct {
+ float frustum_planes[6][4];
+ BoundSphere frustum_bsphere;
+ bool updated;
+ } clipping;
+
+#ifdef USE_GPU_SELECT
+ unsigned int select_id;
+#endif
+
+ /* ---------- Nothing after this point is cleared after use ----------- */
+
+ /* ogl_context serves as the offset for clearing only
+ * the top portion of the struct so DO NOT MOVE IT! */
+ void *ogl_context; /* Unique ghost context used by the draw manager. */
+ Gwn_Context *gwn_context;
+ ThreadMutex ogl_context_mutex; /* Mutex to lock the drw manager and avoid concurent context usage. */
+
+ /** GPU Resource State: Memory storage between drawing. */
+ struct {
+ GPUTexture **bound_texs;
+ char *bound_tex_slots;
+ int bind_tex_inc;
+ GPUUniformBuffer **bound_ubos;
+ char *bound_ubo_slots;
+ int bind_ubo_inc;
+ } RST;
+} DRWManager;
+
+extern DRWManager DST; /* TODO : get rid of this and allow multithreaded rendering */
+
+/* --------------- FUNCTIONS ------------- */
+
+void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags);
+void drw_texture_get_format(
+ DRWTextureFormat format, bool is_framebuffer,
+ GPUTextureFormat *r_data_type, int *r_channels, bool *r_is_depth);
+
+void *drw_viewport_engine_data_ensure(void *engine_type);
+
+void drw_state_set(DRWState state);
+
+#endif /* __DRAW_MANAGER_H__ */
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
new file mode 100644
index 00000000000..ae7854b436c
--- /dev/null
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -0,0 +1,935 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/intern/draw_manager_data.c
+ * \ingroup draw
+ */
+
+#include "draw_manager.h"
+
+#include "BKE_curve.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+
+#include "BLI_link_utils.h"
+#include "BLI_mempool.h"
+
+#include "intern/gpu_codegen.h"
+
+struct Gwn_VertFormat *g_pos_format = NULL;
+
+extern struct GPUUniformBuffer *view_ubo; /* draw_manager_exec.c */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Uniform Buffer Object (DRW_uniformbuffer)
+ * \{ */
+
+GPUUniformBuffer *DRW_uniformbuffer_create(int size, const void *data)
+{
+ return GPU_uniformbuffer_create(size, data, NULL);
+}
+
+void DRW_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data)
+{
+ GPU_uniformbuffer_update(ubo, data);
+}
+
+void DRW_uniformbuffer_free(GPUUniformBuffer *ubo)
+{
+ GPU_uniformbuffer_free(ubo);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Uniforms (DRW_shgroup_uniform)
+ * \{ */
+
+static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup, int loc,
+ DRWUniformType type, const void *value, int length, int arraysize)
+{
+ DRWUniform *uni = BLI_mempool_alloc(DST.vmempool->uniforms);
+ uni->location = loc;
+ uni->type = type;
+ uni->value = value;
+ uni->length = length;
+ uni->arraysize = arraysize;
+
+ BLI_LINKS_PREPEND(shgroup->uniforms, uni);
+}
+
+static void drw_shgroup_builtin_uniform(
+ DRWShadingGroup *shgroup, int builtin, const void *value, int length, int arraysize)
+{
+ int loc = GPU_shader_get_builtin_uniform(shgroup->shader, builtin);
+
+ if (loc != -1) {
+ drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_FLOAT, value, length, arraysize);
+ }
+}
+
+static void drw_shgroup_uniform(DRWShadingGroup *shgroup, const char *name,
+ DRWUniformType type, const void *value, int length, int arraysize)
+{
+ int location;
+ if (ELEM(type, DRW_UNIFORM_BLOCK, DRW_UNIFORM_BLOCK_PERSIST)) {
+ location = GPU_shader_get_uniform_block(shgroup->shader, name);
+ }
+ else {
+ location = GPU_shader_get_uniform(shgroup->shader, name);
+ }
+
+ if (location == -1) {
+ if (G.debug & G_DEBUG)
+ fprintf(stderr, "Uniform '%s' not found!\n", name);
+ /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */
+ // BLI_assert(0);
+ return;
+ }
+
+ BLI_assert(arraysize > 0 && arraysize <= 16);
+ BLI_assert(length >= 0 && length <= 16);
+
+ drw_shgroup_uniform_create_ex(shgroup, location, type, value, length, arraysize);
+}
+
+void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
+{
+ BLI_assert(tex != NULL);
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE, tex, 0, 1);
+}
+
+/* Same as DRW_shgroup_uniform_texture but is garanteed to be bound if shader does not change between shgrp. */
+void DRW_shgroup_uniform_texture_persistent(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
+{
+ BLI_assert(tex != NULL);
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE_PERSIST, tex, 0, 1);
+}
+
+void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const GPUUniformBuffer *ubo)
+{
+ BLI_assert(ubo != NULL);
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BLOCK, ubo, 0, 1);
+}
+
+/* Same as DRW_shgroup_uniform_block but is garanteed to be bound if shader does not change between shgrp. */
+void DRW_shgroup_uniform_block_persistent(DRWShadingGroup *shgroup, const char *name, const GPUUniformBuffer *ubo)
+{
+ BLI_assert(ubo != NULL);
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BLOCK_PERSIST, ubo, 0, 1);
+}
+
+void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
+{
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE_REF, tex, 0, 1);
+}
+
+void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
+{
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BOOL, value, 1, arraysize);
+}
+
+void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
+{
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 1, arraysize);
+}
+
+void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
+{
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 2, arraysize);
+}
+
+void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
+{
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 3, arraysize);
+}
+
+void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
+{
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 4, arraysize);
+}
+
+void DRW_shgroup_uniform_short_to_int(DRWShadingGroup *shgroup, const char *name, const short *value, int arraysize)
+{
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_SHORT_TO_INT, value, 1, arraysize);
+}
+
+void DRW_shgroup_uniform_short_to_float(DRWShadingGroup *shgroup, const char *name, const short *value, int arraysize)
+{
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_SHORT_TO_FLOAT, value, 1, arraysize);
+}
+
+void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
+{
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT, value, 1, arraysize);
+}
+
+void DRW_shgroup_uniform_ivec2(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
+{
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT, value, 2, arraysize);
+}
+
+void DRW_shgroup_uniform_ivec3(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
+{
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT, value, 3, arraysize);
+}
+
+void DRW_shgroup_uniform_mat3(DRWShadingGroup *shgroup, const char *name, const float *value)
+{
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 9, 1);
+}
+
+void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float *value)
+{
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 16, 1);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Draw Call (DRW_calls)
+ * \{ */
+
+static void drw_call_calc_orco(Object *ob, float (*r_orcofacs)[3])
+{
+ ID *ob_data = (ob) ? ob->data : NULL;
+ float *texcoloc = NULL;
+ float *texcosize = NULL;
+ if (ob_data != NULL) {
+ switch (GS(ob_data->name)) {
+ case ID_ME:
+ BKE_mesh_texspace_get_reference((Mesh *)ob_data, NULL, &texcoloc, NULL, &texcosize);
+ break;
+ case ID_CU:
+ {
+ Curve *cu = (Curve *)ob_data;
+ if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_DIRTY)) {
+ BKE_curve_texspace_calc(cu);
+ }
+ texcoloc = cu->loc;
+ texcosize = cu->size;
+ break;
+ }
+ case ID_MB:
+ {
+ MetaBall *mb = (MetaBall *)ob_data;
+ texcoloc = mb->loc;
+ texcosize = mb->size;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if ((texcoloc != NULL) && (texcosize != NULL)) {
+ mul_v3_v3fl(r_orcofacs[1], texcosize, 2.0f);
+ invert_v3(r_orcofacs[1]);
+ sub_v3_v3v3(r_orcofacs[0], texcoloc, texcosize);
+ negate_v3(r_orcofacs[0]);
+ mul_v3_v3(r_orcofacs[0], r_orcofacs[1]); /* result in a nice MADD in the shader */
+ }
+ else {
+ copy_v3_fl(r_orcofacs[0], 0.0f);
+ copy_v3_fl(r_orcofacs[1], 1.0f);
+ }
+}
+
+static DRWCallState *drw_call_state_create(DRWShadingGroup *shgroup, float (*obmat)[4], Object *ob)
+{
+ DRWCallState *state = BLI_mempool_alloc(DST.vmempool->states);
+ state->flag = 0;
+ state->cache_id = 0;
+ state->matflag = shgroup->matflag;
+
+ /* Matrices */
+ if (obmat != NULL) {
+ copy_m4_m4(state->model, obmat);
+
+ if (is_negative_m4(state->model)) {
+ state->flag |= DRW_CALL_NEGSCALE;
+ }
+ }
+ else {
+ unit_m4(state->model);
+ }
+
+ if (ob != NULL) {
+ float corner[3];
+ BoundBox *bbox = BKE_object_boundbox_get(ob);
+ /* Get BoundSphere center and radius from the BoundBox. */
+ mid_v3_v3v3(state->bsphere.center, bbox->vec[0], bbox->vec[6]);
+ mul_v3_m4v3(corner, obmat, bbox->vec[0]);
+ mul_m4_v3(obmat, state->bsphere.center);
+ state->bsphere.radius = len_v3v3(state->bsphere.center, corner);
+ }
+ else {
+ /* Bypass test. */
+ state->bsphere.radius = -1.0f;
+ }
+
+ /* Orco factors: We compute this at creation to not have to save the *ob_data */
+ if ((state->matflag & DRW_CALL_ORCOTEXFAC) != 0) {
+ drw_call_calc_orco(ob, state->orcotexfac);
+ state->matflag &= ~DRW_CALL_ORCOTEXFAC;
+ }
+
+ return state;
+}
+
+static DRWCallState *drw_call_state_object(DRWShadingGroup *shgroup, float (*obmat)[4], Object *ob)
+{
+ if (DST.ob_state == NULL) {
+ DST.ob_state = drw_call_state_create(shgroup, obmat, ob);
+ }
+ else {
+ /* If the DRWCallState is reused, add necessary matrices. */
+ DST.ob_state->matflag |= shgroup->matflag;
+ }
+
+ return DST.ob_state;
+}
+
+void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4])
+{
+ BLI_assert(geom != NULL);
+ BLI_assert(shgroup->type == DRW_SHG_NORMAL);
+
+ DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
+ call->state = drw_call_state_create(shgroup, obmat, NULL);
+ call->type = DRW_CALL_SINGLE;
+ call->single.geometry = geom;
+#ifdef USE_GPU_SELECT
+ call->select_id = DST.select_id;
+#endif
+
+ BLI_LINKS_APPEND(&shgroup->calls, call);
+}
+
+/* These calls can be culled and are optimized for redraw */
+void DRW_shgroup_call_object_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob)
+{
+ BLI_assert(geom != NULL);
+ BLI_assert(shgroup->type == DRW_SHG_NORMAL);
+
+ DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
+ call->state = drw_call_state_object(shgroup, ob->obmat, ob);
+ call->type = DRW_CALL_SINGLE;
+ call->single.geometry = geom;
+#ifdef USE_GPU_SELECT
+ call->select_id = DST.select_id;
+#endif
+
+ BLI_LINKS_APPEND(&shgroup->calls, call);
+}
+
+void DRW_shgroup_call_instances_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4], unsigned int *count)
+{
+ BLI_assert(geom != NULL);
+ BLI_assert(shgroup->type == DRW_SHG_NORMAL);
+
+ DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
+ call->state = drw_call_state_create(shgroup, obmat, NULL);
+ call->type = DRW_CALL_INSTANCES;
+ call->instances.geometry = geom;
+ call->instances.count = count;
+#ifdef USE_GPU_SELECT
+ call->select_id = DST.select_id;
+#endif
+
+ BLI_LINKS_APPEND(&shgroup->calls, call);
+}
+
+/* These calls can be culled and are optimized for redraw */
+void DRW_shgroup_call_object_instances_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob, unsigned int *count)
+{
+ BLI_assert(geom != NULL);
+ BLI_assert(shgroup->type == DRW_SHG_NORMAL);
+
+ DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
+ call->state = drw_call_state_object(shgroup, ob->obmat, ob);
+ call->type = DRW_CALL_INSTANCES;
+ call->instances.geometry = geom;
+ call->instances.count = count;
+#ifdef USE_GPU_SELECT
+ call->select_id = DST.select_id;
+#endif
+
+ BLI_LINKS_APPEND(&shgroup->calls, call);
+}
+
+void DRW_shgroup_call_generate_add(
+ DRWShadingGroup *shgroup,
+ DRWCallGenerateFn *geometry_fn, void *user_data,
+ float (*obmat)[4])
+{
+ BLI_assert(geometry_fn != NULL);
+ BLI_assert(shgroup->type == DRW_SHG_NORMAL);
+
+ DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
+ call->state = drw_call_state_create(shgroup, obmat, NULL);
+ call->type = DRW_CALL_GENERATE;
+ call->generate.geometry_fn = geometry_fn;
+ call->generate.user_data = user_data;
+#ifdef USE_GPU_SELECT
+ call->select_id = DST.select_id;
+#endif
+
+ BLI_LINKS_APPEND(&shgroup->calls, call);
+}
+
+static void sculpt_draw_cb(
+ DRWShadingGroup *shgroup,
+ void (*draw_fn)(DRWShadingGroup *shgroup, Gwn_Batch *geom),
+ void *user_data)
+{
+ Object *ob = user_data;
+ PBVH *pbvh = ob->sculpt->pbvh;
+
+ if (pbvh) {
+ BKE_pbvh_draw_cb(
+ pbvh, NULL, NULL, false,
+ (void (*)(void *, Gwn_Batch *))draw_fn, shgroup);
+ }
+}
+
+void DRW_shgroup_call_sculpt_add(DRWShadingGroup *shgroup, Object *ob, float (*obmat)[4])
+{
+ DRW_shgroup_call_generate_add(shgroup, sculpt_draw_cb, ob, obmat);
+}
+
+void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *attr[], unsigned int attr_len)
+{
+#ifdef USE_GPU_SELECT
+ if (G.f & G_PICKSEL) {
+ if (shgroup->inst_selectid == NULL) {
+ shgroup->inst_selectid = DRW_instance_data_request(DST.idatalist, 1, 128);
+ }
+
+ int *select_id = DRW_instance_data_next(shgroup->inst_selectid);
+ *select_id = DST.select_id;
+ }
+#endif
+
+ BLI_assert(attr_len == shgroup->attribs_count);
+ UNUSED_VARS_NDEBUG(attr_len);
+
+ for (int i = 0; i < attr_len; ++i) {
+ if (shgroup->instance_count == shgroup->instance_vbo->vertex_ct) {
+ GWN_vertbuf_data_resize(shgroup->instance_vbo, shgroup->instance_count + 32);
+ }
+ GWN_vertbuf_attr_set(shgroup->instance_vbo, i, shgroup->instance_count, attr[i]);
+ }
+
+ shgroup->instance_count += 1;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Shading Groups (DRW_shgroup)
+ * \{ */
+
+static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
+{
+ shgroup->instance_geom = NULL;
+ shgroup->instance_vbo = NULL;
+ shgroup->instance_count = 0;
+ shgroup->uniforms = NULL;
+#ifdef USE_GPU_SELECT
+ shgroup->inst_selectid = NULL;
+ shgroup->override_selectid = -1;
+#endif
+#ifndef NDEBUG
+ shgroup->attribs_count = 0;
+#endif
+
+ int view_ubo_location = GPU_shader_get_uniform_block(shader, "viewBlock");
+
+ if (view_ubo_location != -1) {
+ drw_shgroup_uniform_create_ex(shgroup, view_ubo_location, DRW_UNIFORM_BLOCK_PERSIST, view_ubo, 0, 1);
+ }
+ else {
+ /* Only here to support builtin shaders. This should not be used by engines. */
+ drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_VIEW, DST.view_data.matstate.mat[DRW_MAT_VIEW], 16, 1);
+ drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_VIEW_INV, DST.view_data.matstate.mat[DRW_MAT_VIEWINV], 16, 1);
+ drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_VIEWPROJECTION, DST.view_data.matstate.mat[DRW_MAT_PERS], 16, 1);
+ drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_VIEWPROJECTION_INV, DST.view_data.matstate.mat[DRW_MAT_PERSINV], 16, 1);
+ drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_PROJECTION, DST.view_data.matstate.mat[DRW_MAT_WIN], 16, 1);
+ drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_PROJECTION_INV, DST.view_data.matstate.mat[DRW_MAT_WININV], 16, 1);
+ drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_CAMERATEXCO, DST.view_data.viewcamtexcofac, 3, 2);
+ }
+
+ shgroup->model = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODEL);
+ shgroup->modelinverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODEL_INV);
+ shgroup->modelview = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODELVIEW);
+ shgroup->modelviewinverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODELVIEW_INV);
+ shgroup->modelviewprojection = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MVP);
+ shgroup->normalview = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_NORMAL);
+ shgroup->normalworld = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_WORLDNORMAL);
+ shgroup->orcotexfac = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_ORCO);
+ shgroup->eye = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_EYE);
+
+ shgroup->matflag = 0;
+ if (shgroup->modelinverse > -1)
+ shgroup->matflag |= DRW_CALL_MODELINVERSE;
+ if (shgroup->modelview > -1)
+ shgroup->matflag |= DRW_CALL_MODELVIEW;
+ if (shgroup->modelviewinverse > -1)
+ shgroup->matflag |= DRW_CALL_MODELVIEWINVERSE;
+ if (shgroup->modelviewprojection > -1)
+ shgroup->matflag |= DRW_CALL_MODELVIEWPROJECTION;
+ if (shgroup->normalview > -1)
+ shgroup->matflag |= DRW_CALL_NORMALVIEW;
+ if (shgroup->normalworld > -1)
+ shgroup->matflag |= DRW_CALL_NORMALWORLD;
+ if (shgroup->orcotexfac > -1)
+ shgroup->matflag |= DRW_CALL_ORCOTEXFAC;
+ if (shgroup->eye > -1)
+ shgroup->matflag |= DRW_CALL_EYEVEC;
+}
+
+static void drw_shgroup_instance_init(
+ DRWShadingGroup *shgroup, GPUShader *shader, Gwn_Batch *batch, Gwn_VertFormat *format)
+{
+ BLI_assert(shgroup->type == DRW_SHG_INSTANCE);
+ BLI_assert(batch != NULL);
+ BLI_assert(format != NULL);
+
+ drw_shgroup_init(shgroup, shader);
+
+ shgroup->instance_geom = batch;
+#ifndef NDEBUG
+ shgroup->attribs_count = format->attrib_ct;
+#endif
+
+ DRW_instancing_buffer_request(DST.idatalist, format, batch, shgroup,
+ &shgroup->instance_geom, &shgroup->instance_vbo);
+}
+
+static void drw_shgroup_batching_init(
+ DRWShadingGroup *shgroup, GPUShader *shader, Gwn_VertFormat *format)
+{
+ drw_shgroup_init(shgroup, shader);
+
+#ifndef NDEBUG
+ shgroup->attribs_count = (format != NULL) ? format->attrib_ct : 0;
+#endif
+ BLI_assert(format != NULL);
+
+ Gwn_PrimType type;
+ switch (shgroup->type) {
+ case DRW_SHG_POINT_BATCH: type = GWN_PRIM_POINTS; break;
+ case DRW_SHG_LINE_BATCH: type = GWN_PRIM_LINES; break;
+ case DRW_SHG_TRIANGLE_BATCH: type = GWN_PRIM_TRIS; break;
+ default: type = GWN_PRIM_NONE; BLI_assert(0); break;
+ }
+
+ DRW_batching_buffer_request(DST.idatalist, format, type, shgroup,
+ &shgroup->batch_geom, &shgroup->batch_vbo);
+}
+
+static DRWShadingGroup *drw_shgroup_create_ex(struct GPUShader *shader, DRWPass *pass)
+{
+ DRWShadingGroup *shgroup = BLI_mempool_alloc(DST.vmempool->shgroups);
+
+ BLI_LINKS_APPEND(&pass->shgroups, shgroup);
+
+ shgroup->type = DRW_SHG_NORMAL;
+ shgroup->shader = shader;
+ shgroup->state_extra = 0;
+ shgroup->state_extra_disable = ~0x0;
+ shgroup->stencil_mask = 0;
+ shgroup->calls.first = NULL;
+ shgroup->calls.last = NULL;
+#if 0 /* All the same in the union! */
+ shgroup->batch_geom = NULL;
+ shgroup->batch_vbo = NULL;
+
+ shgroup->instance_geom = NULL;
+ shgroup->instance_vbo = NULL;
+#endif
+
+#ifdef USE_GPU_SELECT
+ shgroup->pass_parent = pass;
+#endif
+
+ return shgroup;
+}
+
+static DRWShadingGroup *drw_shgroup_material_create_ex(GPUPass *gpupass, DRWPass *pass)
+{
+ if (!gpupass) {
+ /* Shader compilation error */
+ return NULL;
+ }
+
+ DRWShadingGroup *grp = drw_shgroup_create_ex(GPU_pass_shader(gpupass), pass);
+ return grp;
+}
+
+static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp, struct GPUMaterial *material)
+{
+ /* TODO : Ideally we should not convert. But since the whole codegen
+ * is relying on GPUPass we keep it as is for now. */
+
+ ListBase *inputs = GPU_material_get_inputs(material);
+
+ /* Converting dynamic GPUInput to DRWUniform */
+ for (GPUInput *input = inputs->first; input; input = input->next) {
+ /* Textures */
+ if (input->ima) {
+ double time = 0.0; /* TODO make time variable */
+ GPUTexture *tex = GPU_texture_from_blender(
+ input->ima, input->iuser, input->textarget, input->image_isdata, time, 1);
+
+ if (input->bindtex) {
+ DRW_shgroup_uniform_texture(grp, input->shadername, tex);
+ }
+ }
+ /* Color Ramps */
+ else if (input->tex) {
+ DRW_shgroup_uniform_texture(grp, input->shadername, input->tex);
+ }
+ /* Floats */
+ else {
+ switch (input->type) {
+ case GPU_FLOAT:
+ case GPU_VEC2:
+ case GPU_VEC3:
+ case GPU_VEC4:
+ /* Should already be in the material ubo. */
+ break;
+ case GPU_MAT3:
+ DRW_shgroup_uniform_mat3(grp, input->shadername, (float *)input->dynamicvec);
+ break;
+ case GPU_MAT4:
+ DRW_shgroup_uniform_mat4(grp, input->shadername, (float *)input->dynamicvec);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ GPUUniformBuffer *ubo = GPU_material_get_uniform_buffer(material);
+ if (ubo != NULL) {
+ DRW_shgroup_uniform_block(grp, GPU_UBO_BLOCK_NAME, ubo);
+ }
+
+ return grp;
+}
+
+Gwn_VertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttribFormat attribs[], int arraysize)
+{
+ Gwn_VertFormat *format = MEM_callocN(sizeof(Gwn_VertFormat), "Gwn_VertFormat");
+
+ for (int i = 0; i < arraysize; ++i) {
+ GWN_vertformat_attr_add(format, attribs[i].name,
+ (attribs[i].type == DRW_ATTRIB_INT) ? GWN_COMP_I32 : GWN_COMP_F32,
+ attribs[i].components,
+ (attribs[i].type == DRW_ATTRIB_INT) ? GWN_FETCH_INT : GWN_FETCH_FLOAT);
+ }
+ return format;
+}
+
+DRWShadingGroup *DRW_shgroup_material_create(
+ struct GPUMaterial *material, DRWPass *pass)
+{
+ GPUPass *gpupass = GPU_material_get_pass(material);
+ DRWShadingGroup *shgroup = drw_shgroup_material_create_ex(gpupass, pass);
+
+ if (shgroup) {
+ drw_shgroup_init(shgroup, GPU_pass_shader(gpupass));
+ drw_shgroup_material_inputs(shgroup, material);
+ }
+
+ return shgroup;
+}
+
+DRWShadingGroup *DRW_shgroup_material_instance_create(
+ struct GPUMaterial *material, DRWPass *pass, Gwn_Batch *geom, Object *ob, Gwn_VertFormat *format)
+{
+ GPUPass *gpupass = GPU_material_get_pass(material);
+ DRWShadingGroup *shgroup = drw_shgroup_material_create_ex(gpupass, pass);
+
+ if (shgroup) {
+ shgroup->type = DRW_SHG_INSTANCE;
+ shgroup->instance_geom = geom;
+ drw_call_calc_orco(ob, shgroup->instance_orcofac);
+ drw_shgroup_instance_init(shgroup, GPU_pass_shader(gpupass), geom, format);
+ drw_shgroup_material_inputs(shgroup, material);
+ }
+
+ return shgroup;
+}
+
+DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(
+ struct GPUMaterial *material, DRWPass *pass, int tri_count)
+{
+#ifdef USE_GPU_SELECT
+ BLI_assert((G.f & G_PICKSEL) == 0);
+#endif
+ GPUPass *gpupass = GPU_material_get_pass(material);
+ DRWShadingGroup *shgroup = drw_shgroup_material_create_ex(gpupass, pass);
+
+ if (shgroup) {
+ /* Calling drw_shgroup_init will cause it to call GWN_draw_primitive(). */
+ drw_shgroup_init(shgroup, GPU_pass_shader(gpupass));
+ shgroup->type = DRW_SHG_TRIANGLE_BATCH;
+ shgroup->instance_count = tri_count * 3;
+ drw_shgroup_material_inputs(shgroup, material);
+ }
+
+ return shgroup;
+}
+
+DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
+{
+ DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
+ drw_shgroup_init(shgroup, shader);
+ return shgroup;
+}
+
+DRWShadingGroup *DRW_shgroup_instance_create(
+ struct GPUShader *shader, DRWPass *pass, Gwn_Batch *geom, Gwn_VertFormat *format)
+{
+ DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
+ shgroup->type = DRW_SHG_INSTANCE;
+ shgroup->instance_geom = geom;
+ drw_call_calc_orco(NULL, shgroup->instance_orcofac);
+ drw_shgroup_instance_init(shgroup, shader, geom, format);
+
+ return shgroup;
+}
+
+DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass)
+{
+ DRW_shgroup_instance_format(g_pos_format, {{"pos", DRW_ATTRIB_FLOAT, 3}});
+
+ DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
+ shgroup->type = DRW_SHG_POINT_BATCH;
+
+ drw_shgroup_batching_init(shgroup, shader, g_pos_format);
+
+ return shgroup;
+}
+
+DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass)
+{
+ DRW_shgroup_instance_format(g_pos_format, {{"pos", DRW_ATTRIB_FLOAT, 3}});
+
+ DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
+ shgroup->type = DRW_SHG_LINE_BATCH;
+
+ drw_shgroup_batching_init(shgroup, shader, g_pos_format);
+
+ return shgroup;
+}
+
+/* Very special batch. Use this if you position
+ * your vertices with the vertex shader
+ * and dont need any VBO attrib */
+DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DRWPass *pass, int tri_count)
+{
+#ifdef USE_GPU_SELECT
+ BLI_assert((G.f & G_PICKSEL) == 0);
+#endif
+ DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
+
+ /* Calling drw_shgroup_init will cause it to call GWN_draw_primitive(). */
+ drw_shgroup_init(shgroup, shader);
+
+ shgroup->type = DRW_SHG_TRIANGLE_BATCH;
+ shgroup->instance_count = tri_count * 3;
+
+ return shgroup;
+}
+
+/* Specify an external batch instead of adding each attrib one by one. */
+void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *batch)
+{
+ BLI_assert(shgroup->type == DRW_SHG_INSTANCE);
+ BLI_assert(shgroup->instance_count == 0);
+ /* You cannot use external instancing batch without a dummy format. */
+ BLI_assert(shgroup->attribs_count != 0);
+
+ shgroup->type = DRW_SHG_INSTANCE_EXTERNAL;
+ drw_call_calc_orco(NULL, shgroup->instance_orcofac);
+ /* PERF : This destroys the vaos cache so better check if it's necessary. */
+ /* Note: This WILL break if batch->verts[0] is destroyed and reallocated
+ * at the same adress. Bindings/VAOs would remain obsolete. */
+ //if (shgroup->instancing_geom->inst != batch->verts[0])
+ GWN_batch_instbuf_set(shgroup->instance_geom, batch->verts[0], false);
+
+#ifdef USE_GPU_SELECT
+ shgroup->override_selectid = DST.select_id;
+#endif
+}
+
+unsigned int DRW_shgroup_get_instance_count(const DRWShadingGroup *shgroup)
+{
+ return shgroup->instance_count;
+}
+
+/**
+ * State is added to #Pass.state while drawing.
+ * Use to temporarily enable draw options.
+ */
+void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state)
+{
+ shgroup->state_extra |= state;
+}
+
+void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state)
+{
+ shgroup->state_extra_disable &= ~state;
+}
+
+void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, unsigned int mask)
+{
+ BLI_assert(mask <= 255);
+ shgroup->stencil_mask = mask;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Passes (DRW_pass)
+ * \{ */
+
+DRWPass *DRW_pass_create(const char *name, DRWState state)
+{
+ DRWPass *pass = BLI_mempool_alloc(DST.vmempool->passes);
+ pass->state = state;
+ if (G.debug_value > 20) {
+ BLI_strncpy(pass->name, name, MAX_PASS_NAME);
+ }
+
+ pass->shgroups.first = NULL;
+ pass->shgroups.last = NULL;
+
+ return pass;
+}
+
+void DRW_pass_state_set(DRWPass *pass, DRWState state)
+{
+ pass->state = state;
+}
+
+void DRW_pass_free(DRWPass *pass)
+{
+ pass->shgroups.first = NULL;
+ pass->shgroups.last = NULL;
+}
+
+void DRW_pass_foreach_shgroup(DRWPass *pass, void (*callback)(void *userData, DRWShadingGroup *shgrp), void *userData)
+{
+ for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) {
+ callback(userData, shgroup);
+ }
+}
+
+typedef struct ZSortData {
+ float *axis;
+ float *origin;
+} ZSortData;
+
+static int pass_shgroup_dist_sort(void *thunk, const void *a, const void *b)
+{
+ const ZSortData *zsortdata = (ZSortData *)thunk;
+ const DRWShadingGroup *shgrp_a = (const DRWShadingGroup *)a;
+ const DRWShadingGroup *shgrp_b = (const DRWShadingGroup *)b;
+
+ const DRWCall *call_a = (DRWCall *)shgrp_a->calls.first;
+ const DRWCall *call_b = (DRWCall *)shgrp_b->calls.first;
+
+ if (call_a == NULL) return -1;
+ if (call_b == NULL) return -1;
+
+ float tmp[3];
+ sub_v3_v3v3(tmp, zsortdata->origin, call_a->state->model[3]);
+ const float a_sq = dot_v3v3(zsortdata->axis, tmp);
+ sub_v3_v3v3(tmp, zsortdata->origin, call_b->state->model[3]);
+ const float b_sq = dot_v3v3(zsortdata->axis, tmp);
+
+ if (a_sq < b_sq) return 1;
+ else if (a_sq > b_sq) return -1;
+ else {
+ /* If there is a depth prepass put it before */
+ if ((shgrp_a->state_extra & DRW_STATE_WRITE_DEPTH) != 0) {
+ return -1;
+ }
+ else if ((shgrp_b->state_extra & DRW_STATE_WRITE_DEPTH) != 0) {
+ return 1;
+ }
+ else return 0;
+ }
+}
+
+/* ------------------ Shading group sorting --------------------- */
+
+#define SORT_IMPL_LINKTYPE DRWShadingGroup
+
+#define SORT_IMPL_USE_THUNK
+#define SORT_IMPL_FUNC shgroup_sort_fn_r
+#include "../../blenlib/intern/list_sort_impl.h"
+#undef SORT_IMPL_FUNC
+#undef SORT_IMPL_USE_THUNK
+
+#undef SORT_IMPL_LINKTYPE
+
+/**
+ * Sort Shading groups by decreasing Z of their first draw call.
+ * This is usefull for order dependant effect such as transparency.
+ **/
+void DRW_pass_sort_shgroup_z(DRWPass *pass)
+{
+ float (*viewinv)[4];
+ viewinv = DST.view_data.matstate.mat[DRW_MAT_VIEWINV];
+
+ ZSortData zsortdata = {viewinv[2], viewinv[3]};
+
+ if (pass->shgroups.first && pass->shgroups.first->next) {
+ pass->shgroups.first = shgroup_sort_fn_r(pass->shgroups.first, pass_shgroup_dist_sort, &zsortdata);
+
+ /* Find the next last */
+ DRWShadingGroup *last = pass->shgroups.first;
+ while ((last = last->next)) {
+ /* Do nothing */
+ }
+ pass->shgroups.last = last;
+ }
+}
+
+/** \} */
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
new file mode 100644
index 00000000000..e69a1026815
--- /dev/null
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -0,0 +1,1170 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/intern/draw_manager_exec.c
+ * \ingroup draw
+ */
+
+#include "draw_manager.h"
+
+#include "BLI_mempool.h"
+
+#include "BIF_glutil.h"
+
+#include "BKE_global.h"
+#include "BKE_object.h"
+
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+
+#ifdef USE_GPU_SELECT
+# include "ED_view3d.h"
+# include "ED_armature.h"
+# include "GPU_select.h"
+#endif
+
+#ifdef USE_GPU_SELECT
+void DRW_select_load_id(unsigned int id)
+{
+ BLI_assert(G.f & G_PICKSEL);
+ DST.select_id = id;
+}
+#endif
+
+struct GPUUniformBuffer *view_ubo;
+
+/* -------------------------------------------------------------------- */
+
+/** \name Draw State (DRW_state)
+ * \{ */
+
+void drw_state_set(DRWState state)
+{
+ if (DST.state == state) {
+ return;
+ }
+
+#define CHANGED_TO(f) \
+ ((DST.state_lock & (f)) ? 0 : \
+ (((DST.state & (f)) ? \
+ ((state & (f)) ? 0 : -1) : \
+ ((state & (f)) ? 1 : 0))))
+
+#define CHANGED_ANY(f) \
+ (((DST.state & (f)) != (state & (f))) && \
+ ((DST.state_lock & (f)) == 0))
+
+#define CHANGED_ANY_STORE_VAR(f, enabled) \
+ (((DST.state & (f)) != (enabled = (state & (f)))) && \
+ (((DST.state_lock & (f)) == 0)))
+
+ /* Depth Write */
+ {
+ int test;
+ if ((test = CHANGED_TO(DRW_STATE_WRITE_DEPTH))) {
+ if (test == 1) {
+ glDepthMask(GL_TRUE);
+ }
+ else {
+ glDepthMask(GL_FALSE);
+ }
+ }
+ }
+
+ /* Color Write */
+ {
+ int test;
+ if ((test = CHANGED_TO(DRW_STATE_WRITE_COLOR))) {
+ if (test == 1) {
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+ else {
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ }
+ }
+ }
+
+ /* Cull */
+ {
+ DRWState test;
+ if (CHANGED_ANY_STORE_VAR(
+ DRW_STATE_CULL_BACK | DRW_STATE_CULL_FRONT,
+ test))
+ {
+ if (test) {
+ glEnable(GL_CULL_FACE);
+
+ if ((state & DRW_STATE_CULL_BACK) != 0) {
+ glCullFace(GL_BACK);
+ }
+ else if ((state & DRW_STATE_CULL_FRONT) != 0) {
+ glCullFace(GL_FRONT);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ glDisable(GL_CULL_FACE);
+ }
+ }
+ }
+
+ /* Depth Test */
+ {
+ DRWState test;
+ if (CHANGED_ANY_STORE_VAR(
+ DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER | DRW_STATE_DEPTH_ALWAYS,
+ test))
+ {
+ if (test) {
+ glEnable(GL_DEPTH_TEST);
+
+ if (state & DRW_STATE_DEPTH_LESS) {
+ glDepthFunc(GL_LEQUAL);
+ }
+ else if (state & DRW_STATE_DEPTH_EQUAL) {
+ glDepthFunc(GL_EQUAL);
+ }
+ else if (state & DRW_STATE_DEPTH_GREATER) {
+ glDepthFunc(GL_GREATER);
+ }
+ else if (state & DRW_STATE_DEPTH_ALWAYS) {
+ glDepthFunc(GL_ALWAYS);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ glDisable(GL_DEPTH_TEST);
+ }
+ }
+ }
+
+ /* Wire Width */
+ {
+ if (CHANGED_ANY(DRW_STATE_WIRE)) {
+ if ((state & DRW_STATE_WIRE) != 0) {
+ glLineWidth(1.0f);
+ }
+ else {
+ /* do nothing */
+ }
+ }
+ }
+
+ /* Points Size */
+ {
+ int test;
+ if ((test = CHANGED_TO(DRW_STATE_POINT))) {
+ if (test == 1) {
+ GPU_enable_program_point_size();
+ glPointSize(5.0f);
+ }
+ else {
+ GPU_disable_program_point_size();
+ }
+ }
+ }
+
+ /* Blending (all buffer) */
+ {
+ int test;
+ if (CHANGED_ANY_STORE_VAR(
+ DRW_STATE_BLEND | DRW_STATE_ADDITIVE | DRW_STATE_MULTIPLY | DRW_STATE_TRANSMISSION |
+ DRW_STATE_ADDITIVE_FULL,
+ test))
+ {
+ if (test) {
+ glEnable(GL_BLEND);
+
+ if ((state & DRW_STATE_BLEND) != 0) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, /* RGB */
+ GL_ONE, GL_ONE_MINUS_SRC_ALPHA); /* Alpha */
+ }
+ else if ((state & DRW_STATE_MULTIPLY) != 0) {
+ glBlendFunc(GL_DST_COLOR, GL_ZERO);
+ }
+ else if ((state & DRW_STATE_TRANSMISSION) != 0) {
+ glBlendFunc(GL_ONE, GL_SRC_ALPHA);
+ }
+ else if ((state & DRW_STATE_ADDITIVE) != 0) {
+ /* Do not let alpha accumulate but premult the source RGB by it. */
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, /* RGB */
+ GL_ZERO, GL_ONE); /* Alpha */
+ }
+ else if ((state & DRW_STATE_ADDITIVE_FULL) != 0) {
+ /* Let alpha accumulate. */
+ glBlendFunc(GL_ONE, GL_ONE);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ glDisable(GL_BLEND);
+ }
+ }
+ }
+
+ /* Clip Planes */
+ {
+ int test;
+ if ((test = CHANGED_TO(DRW_STATE_CLIP_PLANES))) {
+ if (test == 1) {
+ for (int i = 0; i < DST.num_clip_planes; ++i) {
+ glEnable(GL_CLIP_DISTANCE0 + i);
+ }
+ }
+ else {
+ for (int i = 0; i < MAX_CLIP_PLANES; ++i) {
+ glDisable(GL_CLIP_DISTANCE0 + i);
+ }
+ }
+ }
+ }
+
+ /* Line Stipple */
+ {
+ int test;
+ if (CHANGED_ANY_STORE_VAR(
+ DRW_STATE_STIPPLE_2 | DRW_STATE_STIPPLE_3 | DRW_STATE_STIPPLE_4,
+ test))
+ {
+ if (test) {
+ if ((state & DRW_STATE_STIPPLE_2) != 0) {
+ setlinestyle(2);
+ }
+ else if ((state & DRW_STATE_STIPPLE_3) != 0) {
+ setlinestyle(3);
+ }
+ else if ((state & DRW_STATE_STIPPLE_4) != 0) {
+ setlinestyle(4);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ setlinestyle(0);
+ }
+ }
+ }
+
+ /* Stencil */
+ {
+ DRWState test;
+ if (CHANGED_ANY_STORE_VAR(
+ DRW_STATE_WRITE_STENCIL |
+ DRW_STATE_STENCIL_EQUAL,
+ test))
+ {
+ if (test) {
+ glEnable(GL_STENCIL_TEST);
+
+ /* Stencil Write */
+ if ((state & DRW_STATE_WRITE_STENCIL) != 0) {
+ glStencilMask(0xFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ }
+ /* Stencil Test */
+ else if ((state & DRW_STATE_STENCIL_EQUAL) != 0) {
+ glStencilMask(0x00); /* disable write */
+ DST.stencil_mask = 0;
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ /* disable write & test */
+ DST.stencil_mask = 0;
+ glStencilMask(0x00);
+ glStencilFunc(GL_ALWAYS, 1, 0xFF);
+ glDisable(GL_STENCIL_TEST);
+ }
+ }
+ }
+
+#undef CHANGED_TO
+#undef CHANGED_ANY
+#undef CHANGED_ANY_STORE_VAR
+
+ DST.state = state;
+}
+
+static void drw_stencil_set(unsigned int mask)
+{
+ if (DST.stencil_mask != mask) {
+ /* Stencil Write */
+ if ((DST.state & DRW_STATE_WRITE_STENCIL) != 0) {
+ glStencilFunc(GL_ALWAYS, mask, 0xFF);
+ DST.stencil_mask = mask;
+ }
+ /* Stencil Test */
+ else if ((DST.state & DRW_STATE_STENCIL_EQUAL) != 0) {
+ glStencilFunc(GL_EQUAL, mask, 0xFF);
+ DST.stencil_mask = mask;
+ }
+ }
+}
+
+/* Reset state to not interfer with other UI drawcall */
+void DRW_state_reset_ex(DRWState state)
+{
+ DST.state = ~state;
+ drw_state_set(state);
+}
+
+/**
+ * Use with care, intended so selection code can override passes depth settings,
+ * which is important for selection to work properly.
+ *
+ * Should be set in main draw loop, cleared afterwards
+ */
+void DRW_state_lock(DRWState state)
+{
+ DST.state_lock = state;
+}
+
+void DRW_state_reset(void)
+{
+ /* Reset blending function */
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ DRW_state_reset_ex(DRW_STATE_DEFAULT);
+}
+
+/* NOTE : Make sure to reset after use! */
+void DRW_state_invert_facing(void)
+{
+ SWAP(GLenum, DST.backface, DST.frontface);
+ glFrontFace(DST.frontface);
+}
+
+/**
+ * This only works if DRWPasses have been tagged with DRW_STATE_CLIP_PLANES,
+ * and if the shaders have support for it (see usage of gl_ClipDistance).
+ * Be sure to call DRW_state_clip_planes_reset() after you finish drawing.
+ **/
+void DRW_state_clip_planes_count_set(unsigned int plane_ct)
+{
+ BLI_assert(plane_ct <= MAX_CLIP_PLANES);
+ DST.num_clip_planes = plane_ct;
+}
+
+void DRW_state_clip_planes_reset(void)
+{
+ DST.num_clip_planes = 0;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Clipping (DRW_clipping)
+ * \{ */
+
+/* Extract the 8 corners (world space).
+ * Although less accurate, this solution can be simplified as follows:
+ *
+ * BKE_boundbox_init_from_minmax(&bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const float[3]){1.0f, 1.0f, 1.0f});
+ * for (int i = 0; i < 8; i++) {mul_project_m4_v3(viewprojinv, bbox.vec[i]);}
+ */
+static void draw_frustum_boundbox_calc(const float (*projmat)[4], const float (*viewinv)[4], BoundBox *r_bbox)
+{
+ float screenvecs[3][3], loc[3], near, far, w_half, h_half;
+ bool is_persp = projmat[3][3] == 0.0f;
+ copy_m3_m4(screenvecs, viewinv);
+ copy_v3_v3(loc, viewinv[3]);
+
+ /* get the values of the minimum and maximum clipping planes distances
+ * and half the width and height of the nearplane rectangle. */
+ if (is_persp) {
+ near = projmat[3][2] / (projmat[2][2] - 1.0f);
+ far = projmat[3][2] / (projmat[2][2] + 1.0f);
+ w_half = near / projmat[0][0];
+ h_half = near / projmat[1][1];
+ }
+ else {
+ near = (projmat[3][2] + 1.0f) / projmat[2][2];
+ far = (projmat[3][2] - 1.0f) / projmat[2][2];
+ w_half = 1.0f / projmat[0][0];
+ h_half = 1.0f / projmat[1][1];
+ }
+
+ /* With vectors aligned to the screen, reconstruct
+ * the near plane from the dimensions obtained earlier. */
+ float mid[3], hor[3], ver[3];
+ mul_v3_v3fl(hor, screenvecs[0], w_half);
+ mul_v3_v3fl(ver, screenvecs[1], h_half);
+ madd_v3_v3v3fl(mid, loc, screenvecs[2], -near);
+
+ /* The case below is for non-symmetric frustum. */
+ if (is_persp) {
+ madd_v3_v3fl(mid, hor, projmat[2][0]);
+ madd_v3_v3fl(mid, ver, projmat[2][1]);
+ }
+ else {
+ madd_v3_v3fl(mid, hor, projmat[3][0]);
+ madd_v3_v3fl(mid, ver, projmat[3][1]);
+ }
+
+ r_bbox->vec[0][0] = mid[0] - ver[0] - hor[0];
+ r_bbox->vec[0][1] = mid[1] - ver[1] - hor[1];
+ r_bbox->vec[0][2] = mid[2] - ver[2] - hor[2];
+
+ r_bbox->vec[3][0] = mid[0] + ver[0] - hor[0];
+ r_bbox->vec[3][1] = mid[1] + ver[1] - hor[1];
+ r_bbox->vec[3][2] = mid[2] + ver[2] - hor[2];
+
+ r_bbox->vec[7][0] = mid[0] + ver[0] + hor[0];
+ r_bbox->vec[7][1] = mid[1] + ver[1] + hor[1];
+ r_bbox->vec[7][2] = mid[2] + ver[2] + hor[2];
+
+ r_bbox->vec[4][0] = mid[0] - ver[0] + hor[0];
+ r_bbox->vec[4][1] = mid[1] - ver[1] + hor[1];
+ r_bbox->vec[4][2] = mid[2] - ver[2] + hor[2];
+
+ /* Get the coordinates of the far plane. */
+ if (is_persp) {
+ float sca_far = far / near;
+ mid[0] = mid[0] + (mid[0] - loc[0]) * sca_far;
+ mid[1] = mid[1] + (mid[1] - loc[1]) * sca_far;
+ mid[2] = mid[2] + (mid[2] - loc[2]) * sca_far;
+
+ mul_v3_fl(hor, sca_far);
+ mul_v3_fl(ver, sca_far);
+ }
+ else {
+ madd_v3_v3v3fl(mid, loc, screenvecs[2], -far);
+
+ /* Non-symmetric frustum. */
+ madd_v3_v3fl(mid, hor, projmat[3][0]);
+ madd_v3_v3fl(mid, ver, projmat[3][1]);
+ }
+
+ r_bbox->vec[1][0] = mid[0] - ver[0] - hor[0];
+ r_bbox->vec[1][1] = mid[1] - ver[1] - hor[1];
+ r_bbox->vec[1][2] = mid[2] - ver[2] - hor[2];
+
+ r_bbox->vec[2][0] = mid[0] + ver[0] - hor[0];
+ r_bbox->vec[2][1] = mid[1] + ver[1] - hor[1];
+ r_bbox->vec[2][2] = mid[2] + ver[2] - hor[2];
+
+ r_bbox->vec[6][0] = mid[0] + ver[0] + hor[0];
+ r_bbox->vec[6][1] = mid[1] + ver[1] + hor[1];
+ r_bbox->vec[6][2] = mid[2] + ver[2] + hor[2];
+
+ r_bbox->vec[5][0] = mid[0] - ver[0] + hor[0];
+ r_bbox->vec[5][1] = mid[1] - ver[1] + hor[1];
+ r_bbox->vec[5][2] = mid[2] - ver[2] + hor[2];
+}
+
+static void draw_clipping_setup_from_view(void)
+{
+ if (DST.clipping.updated)
+ return;
+
+ float (*viewinv)[4] = DST.view_data.matstate.mat[DRW_MAT_VIEWINV];
+ float (*projmat)[4] = DST.view_data.matstate.mat[DRW_MAT_WIN];
+ float (*projinv)[4] = DST.view_data.matstate.mat[DRW_MAT_WININV];
+ BoundSphere *bsphere = &DST.clipping.frustum_bsphere;
+
+ /* Extract Clipping Planes */
+ BoundBox bbox;
+ draw_frustum_boundbox_calc(projmat, viewinv, &bbox);
+
+ /* Compute clip planes using the world space frustum corners. */
+ for (int p = 0; p < 6; p++) {
+ int q, r;
+ switch (p) {
+ case 0: q=1; r=2; break;
+ case 1: q=0; r=5; break;
+ case 2: q=1; r=5; break;
+ case 3: q=2; r=6; break;
+ case 4: q=0; r=3; break;
+ default: q=4; r=7; break;
+ }
+ if (DST.frontface == GL_CW) {
+ SWAP(int, q, r);
+ }
+
+ normal_tri_v3(DST.clipping.frustum_planes[p], bbox.vec[p], bbox.vec[q], bbox.vec[r]);
+ DST.clipping.frustum_planes[p][3] = -dot_v3v3(DST.clipping.frustum_planes[p], bbox.vec[p]);
+ }
+
+ /* Extract Bounding Sphere */
+ if (projmat[3][3] != 0.0f) {
+ /* Orthographic */
+ /* The most extreme points on the near and far plane. (normalized device coords). */
+ float *nearpoint = bbox.vec[0];
+ float *farpoint = bbox.vec[6];
+
+ mul_project_m4_v3(projinv, nearpoint);
+ mul_project_m4_v3(projinv, farpoint);
+
+ /* just use median point */
+ mid_v3_v3v3(bsphere->center, farpoint, nearpoint);
+ bsphere->radius = len_v3v3(bsphere->center, farpoint);
+ }
+ else if (projmat[2][0] == 0.0f && projmat[2][1] == 0.0f) {
+ /* Perspective with symmetrical frustum. */
+
+ /* We obtain the center and radius of the circumscribed circle of the
+ * isosceles trapezoid composed by the diagonals of the near and far clipping plane */
+
+ /* center of each clipping plane */
+ float mid_min[3], mid_max[3];
+ mid_v3_v3v3(mid_min, bbox.vec[3], bbox.vec[4]);
+ mid_v3_v3v3(mid_max, bbox.vec[2], bbox.vec[5]);
+
+ /* square length of the diagonals of each clipping plane */
+ float a_sq = len_squared_v3v3(bbox.vec[3], bbox.vec[4]);
+ float b_sq = len_squared_v3v3(bbox.vec[2], bbox.vec[5]);
+
+ /* distance squared between clipping planes */
+ float h_sq = len_squared_v3v3(mid_min, mid_max);
+
+ float fac = (4 * h_sq + b_sq - a_sq) / (8 * h_sq);
+ BLI_assert(fac >= 0.0f);
+
+ /* The goal is to get the smallest sphere,
+ * not the sphere that passes through each corner */
+ CLAMP(fac, 0.0f, 1.0f);
+
+ interp_v3_v3v3(bsphere->center, mid_min, mid_max, fac);
+
+ /* distance from the center to one of the points of the far plane (1, 2, 5, 6) */
+ bsphere->radius = len_v3v3(bsphere->center, bbox.vec[1]);
+ }
+ else {
+ /* Perspective with asymmetrical frustum. */
+
+ /* We put the sphere center on the line that goes from origin
+ * to the center of the far clipping plane. */
+
+ /* Detect which of the corner of the far clipping plane is the farthest to the origin */
+ float nfar[4]; /* most extreme far point in NDC space */
+ float farxy[2]; /* farpoint projection onto the near plane */
+ float farpoint[3] = {0.0f}; /* most extreme far point in camera coordinate */
+ float nearpoint[3]; /* most extreme near point in camera coordinate */
+ float farcenter[3] = {0.0f}; /* center of far cliping plane in camera coordinate */
+ float F = -1.0f, N; /* square distance of far and near point to origin */
+ float f, n; /* distance of far and near point to z axis. f is always > 0 but n can be < 0 */
+ float e, s; /* far and near clipping distance (<0) */
+ float c; /* slope of center line = distance of far clipping center to z axis / far clipping distance */
+ float z; /* projection of sphere center on z axis (<0) */
+
+ /* Find farthest corner and center of far clip plane. */
+ float corner[3] = {1.0f, 1.0f, 1.0f}; /* in clip space */
+ for (int i = 0; i < 4; i++) {
+ float point[3];
+ mul_v3_project_m4_v3(point, projinv, corner);
+ float len = len_squared_v3(point);
+ if (len > F) {
+ copy_v3_v3(nfar, corner);
+ copy_v3_v3(farpoint, point);
+ F = len;
+ }
+ add_v3_v3(farcenter, point);
+ /* rotate by 90 degree to walk through the 4 points of the far clip plane */
+ float tmp = corner[0];
+ corner[0] = -corner[1];
+ corner[1] = tmp;
+ }
+
+ /* the far center is the average of the far clipping points */
+ mul_v3_fl(farcenter, 0.25f);
+ /* the extreme near point is the opposite point on the near clipping plane */
+ copy_v3_fl3(nfar, -nfar[0], -nfar[1], -1.0f);
+ mul_v3_project_m4_v3(nearpoint, projinv, nfar);
+ /* this is a frustum projection */
+ N = len_squared_v3(nearpoint);
+ e = farpoint[2];
+ s = nearpoint[2];
+ /* distance to view Z axis */
+ f = len_v2(farpoint);
+ /* get corresponding point on the near plane */
+ mul_v2_v2fl(farxy, farpoint, s/e);
+ /* this formula preserve the sign of n */
+ sub_v2_v2(nearpoint, farxy);
+ n = f * s / e - len_v2(nearpoint);
+ c = len_v2(farcenter) / e;
+ /* the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case */
+ z = (F-N) / (2.0f * (e-s + c*(f-n)));
+
+ bsphere->center[0] = farcenter[0] * z/e;
+ bsphere->center[1] = farcenter[1] * z/e;
+ bsphere->center[2] = z;
+ bsphere->radius = len_v3v3(bsphere->center, farpoint);
+
+ /* Transform to world space. */
+ mul_m4_v3(viewinv, bsphere->center);
+ }
+
+ DST.clipping.updated = true;
+}
+
+/* Return True if the given BoundSphere intersect the current view frustum */
+bool DRW_culling_sphere_test(BoundSphere *bsphere)
+{
+ draw_clipping_setup_from_view();
+
+ /* Bypass test if radius is negative. */
+ if (bsphere->radius < 0.0f)
+ return true;
+
+ /* Do a rough test first: Sphere VS Sphere intersect. */
+ BoundSphere *frustum_bsphere = &DST.clipping.frustum_bsphere;
+ float center_dist = len_squared_v3v3(bsphere->center, frustum_bsphere->center);
+ if (center_dist > SQUARE(bsphere->radius + frustum_bsphere->radius))
+ return false;
+
+ /* Test against the 6 frustum planes. */
+ for (int p = 0; p < 6; p++) {
+ float dist = plane_point_side_v3(DST.clipping.frustum_planes[p], bsphere->center);
+ if (dist < -bsphere->radius) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Return True if the given BoundBox intersect the current view frustum.
+ * bbox must be in world space. */
+bool DRW_culling_box_test(BoundBox *bbox)
+{
+ draw_clipping_setup_from_view();
+
+ /* 6 view frustum planes */
+ for (int p = 0; p < 6; p++) {
+ /* 8 box vertices. */
+ for (int v = 0; v < 8 ; v++) {
+ float dist = plane_point_side_v3(DST.clipping.frustum_planes[p], bbox->vec[v]);
+ if (dist > 0.0f) {
+ /* At least one point in front of this plane.
+ * Go to next plane. */
+ break;
+ }
+ else if (v == 7) {
+ /* 8 points behind this plane. */
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Draw (DRW_draw)
+ * \{ */
+
+static void draw_matrices_model_prepare(DRWCallState *st)
+{
+ if (st->cache_id == DST.state_cache_id) {
+ return; /* Values are already updated for this view. */
+ }
+ else {
+ st->cache_id = DST.state_cache_id;
+ }
+
+ if (DRW_culling_sphere_test(&st->bsphere)) {
+ st->flag &= ~DRW_CALL_CULLED;
+ }
+ else {
+ st->flag |= DRW_CALL_CULLED;
+ return; /* No need to go further the call will not be used. */
+ }
+
+ /* Order matters */
+ if (st->matflag & (DRW_CALL_MODELVIEW | DRW_CALL_MODELVIEWINVERSE |
+ DRW_CALL_NORMALVIEW | DRW_CALL_EYEVEC))
+ {
+ mul_m4_m4m4(st->modelview, DST.view_data.matstate.mat[DRW_MAT_VIEW], st->model);
+ }
+ if (st->matflag & DRW_CALL_MODELVIEWINVERSE) {
+ invert_m4_m4(st->modelviewinverse, st->modelview);
+ }
+ if (st->matflag & DRW_CALL_MODELVIEWPROJECTION) {
+ mul_m4_m4m4(st->modelviewprojection, DST.view_data.matstate.mat[DRW_MAT_PERS], st->model);
+ }
+ if (st->matflag & (DRW_CALL_NORMALVIEW | DRW_CALL_EYEVEC)) {
+ copy_m3_m4(st->normalview, st->modelview);
+ invert_m3(st->normalview);
+ transpose_m3(st->normalview);
+ }
+ if (st->matflag & DRW_CALL_EYEVEC) {
+ /* Used by orthographic wires */
+ float tmp[3][3];
+ copy_v3_fl3(st->eyevec, 0.0f, 0.0f, 1.0f);
+ invert_m3_m3(tmp, st->normalview);
+ /* set eye vector, transformed to object coords */
+ mul_m3_v3(tmp, st->eyevec);
+ }
+ /* Non view dependant */
+ if (st->matflag & DRW_CALL_MODELINVERSE) {
+ invert_m4_m4(st->modelinverse, st->model);
+ st->matflag &= ~DRW_CALL_MODELINVERSE;
+ }
+ if (st->matflag & DRW_CALL_NORMALWORLD) {
+ copy_m3_m4(st->normalworld, st->model);
+ invert_m3(st->normalworld);
+ transpose_m3(st->normalworld);
+ st->matflag &= ~DRW_CALL_NORMALWORLD;
+ }
+}
+
+static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCallState *state)
+{
+ /* step 1 : bind object dependent matrices */
+ if (state != NULL) {
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)state->model);
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->modelinverse, 16, 1, (float *)state->modelinverse);
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->modelview, 16, 1, (float *)state->modelview);
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewinverse, 16, 1, (float *)state->modelviewinverse);
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewprojection, 16, 1, (float *)state->modelviewprojection);
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->normalview, 9, 1, (float *)state->normalview);
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->normalworld, 9, 1, (float *)state->normalworld);
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)state->orcotexfac);
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->eye, 3, 1, (float *)state->eyevec);
+ }
+ else {
+ BLI_assert((shgroup->normalview == -1) && (shgroup->normalworld == -1) && (shgroup->eye == -1));
+ /* For instancing and batching. */
+ float unitmat[4][4];
+ unit_m4(unitmat);
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)unitmat);
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->modelinverse, 16, 1, (float *)unitmat);
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->modelview, 16, 1, (float *)DST.view_data.matstate.mat[DRW_MAT_VIEW]);
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewinverse, 16, 1, (float *)DST.view_data.matstate.mat[DRW_MAT_VIEWINV]);
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewprojection, 16, 1, (float *)DST.view_data.matstate.mat[DRW_MAT_PERS]);
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)shgroup->instance_orcofac);
+ }
+}
+
+static void draw_geometry_execute_ex(
+ DRWShadingGroup *shgroup, Gwn_Batch *geom, unsigned int start, unsigned int count, bool draw_instance)
+{
+ /* Special case: empty drawcall, placement is done via shader, don't bind anything. */
+ if (geom == NULL) {
+ BLI_assert(shgroup->type == DRW_SHG_TRIANGLE_BATCH); /* Add other type if needed. */
+ /* Shader is already bound. */
+ GWN_draw_primitive(GWN_PRIM_TRIS, count);
+ return;
+ }
+
+ /* step 2 : bind vertex array & draw */
+ GWN_batch_program_set_no_use(geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
+ /* XXX hacking gawain. we don't want to call glUseProgram! (huge performance loss) */
+ geom->program_in_use = true;
+
+ GWN_batch_draw_range_ex(geom, start, count, draw_instance);
+
+ geom->program_in_use = false; /* XXX hacking gawain */
+}
+
+static void draw_geometry_execute(DRWShadingGroup *shgroup, Gwn_Batch *geom)
+{
+ draw_geometry_execute_ex(shgroup, geom, 0, 0, false);
+}
+
+enum {
+ BIND_NONE = 0,
+ BIND_TEMP = 1, /* Release slot after this shading group. */
+ BIND_PERSIST = 2, /* Release slot only after the next shader change. */
+};
+
+static void bind_texture(GPUTexture *tex, char bind_type)
+{
+ int index;
+ char *slot_flags = DST.RST.bound_tex_slots;
+ int bind_num = GPU_texture_bound_number(tex);
+ if (bind_num == -1) {
+ for (int i = 0; i < GPU_max_textures(); ++i) {
+ index = DST.RST.bind_tex_inc = (DST.RST.bind_tex_inc + 1) % GPU_max_textures();
+ if (slot_flags[index] == BIND_NONE) {
+ if (DST.RST.bound_texs[index] != NULL) {
+ GPU_texture_unbind(DST.RST.bound_texs[index]);
+ }
+ GPU_texture_bind(tex, index);
+ DST.RST.bound_texs[index] = tex;
+ slot_flags[index] = bind_type;
+ // printf("Binds Texture %d %p\n", DST.RST.bind_tex_inc, tex);
+ return;
+ }
+ }
+ printf("Not enough texture slots! Reduce number of textures used by your shader.\n");
+ }
+ slot_flags[bind_num] = bind_type;
+}
+
+static void bind_ubo(GPUUniformBuffer *ubo, char bind_type)
+{
+ int index;
+ char *slot_flags = DST.RST.bound_ubo_slots;
+ int bind_num = GPU_uniformbuffer_bindpoint(ubo);
+ if (bind_num == -1) {
+ for (int i = 0; i < GPU_max_ubo_binds(); ++i) {
+ index = DST.RST.bind_ubo_inc = (DST.RST.bind_ubo_inc + 1) % GPU_max_ubo_binds();
+ if (slot_flags[index] == BIND_NONE) {
+ if (DST.RST.bound_ubos[index] != NULL) {
+ GPU_uniformbuffer_unbind(DST.RST.bound_ubos[index]);
+ }
+ GPU_uniformbuffer_bind(ubo, index);
+ DST.RST.bound_ubos[index] = ubo;
+ slot_flags[index] = bind_type;
+ return;
+ }
+ }
+ /* printf so user can report bad behaviour */
+ printf("Not enough ubo slots! This should not happen!\n");
+ /* This is not depending on user input.
+ * It is our responsability to make sure there is enough slots. */
+ BLI_assert(0);
+ }
+ slot_flags[bind_num] = bind_type;
+}
+
+static void release_texture_slots(bool with_persist)
+{
+ if (with_persist) {
+ memset(DST.RST.bound_tex_slots, 0x0, sizeof(*DST.RST.bound_tex_slots) * GPU_max_textures());
+ }
+ else {
+ for (int i = 0; i < GPU_max_textures(); ++i) {
+ if (DST.RST.bound_tex_slots[i] != BIND_PERSIST)
+ DST.RST.bound_tex_slots[i] = BIND_NONE;
+ }
+ }
+
+ /* Reset so that slots are consistenly assigned for different shader
+ * draw calls, to avoid shader specialization/patching by the driver. */
+ DST.RST.bind_tex_inc = 0;
+}
+
+static void release_ubo_slots(bool with_persist)
+{
+ if (with_persist) {
+ memset(DST.RST.bound_ubo_slots, 0x0, sizeof(*DST.RST.bound_ubo_slots) * GPU_max_ubo_binds());
+ }
+ else {
+ for (int i = 0; i < GPU_max_ubo_binds(); ++i) {
+ if (DST.RST.bound_ubo_slots[i] != BIND_PERSIST)
+ DST.RST.bound_ubo_slots[i] = BIND_NONE;
+ }
+ }
+
+ /* Reset so that slots are consistenly assigned for different shader
+ * draw calls, to avoid shader specialization/patching by the driver. */
+ DST.RST.bind_ubo_inc = 0;
+}
+
+static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
+{
+ BLI_assert(shgroup->shader);
+
+ GPUTexture *tex;
+ GPUUniformBuffer *ubo;
+ int val;
+ float fval;
+ const bool shader_changed = (DST.shader != shgroup->shader);
+
+ if (shader_changed) {
+ if (DST.shader) GPU_shader_unbind();
+ GPU_shader_bind(shgroup->shader);
+ DST.shader = shgroup->shader;
+ }
+
+ release_ubo_slots(shader_changed);
+ release_texture_slots(shader_changed);
+
+ drw_state_set((pass_state & shgroup->state_extra_disable) | shgroup->state_extra);
+ drw_stencil_set(shgroup->stencil_mask);
+
+ /* Binding Uniform */
+ /* Don't check anything, Interface should already contain the least uniform as possible */
+ for (DRWUniform *uni = shgroup->uniforms; uni; uni = uni->next) {
+ switch (uni->type) {
+ case DRW_UNIFORM_SHORT_TO_INT:
+ val = (int)*((short *)uni->value);
+ GPU_shader_uniform_vector_int(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, (int *)&val);
+ break;
+ case DRW_UNIFORM_SHORT_TO_FLOAT:
+ fval = (float)*((short *)uni->value);
+ GPU_shader_uniform_vector(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)&fval);
+ break;
+ case DRW_UNIFORM_BOOL:
+ case DRW_UNIFORM_INT:
+ GPU_shader_uniform_vector_int(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, (int *)uni->value);
+ break;
+ case DRW_UNIFORM_FLOAT:
+ GPU_shader_uniform_vector(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)uni->value);
+ break;
+ case DRW_UNIFORM_TEXTURE:
+ tex = (GPUTexture *)uni->value;
+ BLI_assert(tex);
+ bind_texture(tex, BIND_TEMP);
+ GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
+ break;
+ case DRW_UNIFORM_TEXTURE_PERSIST:
+ tex = (GPUTexture *)uni->value;
+ BLI_assert(tex);
+ bind_texture(tex, BIND_PERSIST);
+ GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
+ break;
+ case DRW_UNIFORM_TEXTURE_REF:
+ tex = *((GPUTexture **)uni->value);
+ BLI_assert(tex);
+ bind_texture(tex, BIND_TEMP);
+ GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
+ break;
+ case DRW_UNIFORM_BLOCK:
+ ubo = (GPUUniformBuffer *)uni->value;
+ bind_ubo(ubo, BIND_TEMP);
+ GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ break;
+ case DRW_UNIFORM_BLOCK_PERSIST:
+ ubo = (GPUUniformBuffer *)uni->value;
+ bind_ubo(ubo, BIND_PERSIST);
+ GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ break;
+ }
+ }
+
+#ifdef USE_GPU_SELECT
+# define GPU_SELECT_LOAD_IF_PICKSEL(_select_id) \
+ if (G.f & G_PICKSEL) { \
+ GPU_select_load_id(_select_id); \
+ } ((void)0)
+
+# define GPU_SELECT_LOAD_IF_PICKSEL_CALL(_call) \
+ if ((G.f & G_PICKSEL) && (_call)) { \
+ GPU_select_load_id((_call)->select_id); \
+ } ((void)0)
+
+# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_shgroup, _start, _count) \
+ _start = 0; \
+ _count = _shgroup->instance_count; \
+ int *select_id = NULL; \
+ if (G.f & G_PICKSEL) { \
+ if (_shgroup->override_selectid == -1) { \
+ select_id = DRW_instance_data_get(_shgroup->inst_selectid); \
+ switch (_shgroup->type) { \
+ case DRW_SHG_TRIANGLE_BATCH: _count = 3; break; \
+ case DRW_SHG_LINE_BATCH: _count = 2; break; \
+ default: _count = 1; break; \
+ } \
+ } \
+ else { \
+ GPU_select_load_id(_shgroup->override_selectid); \
+ } \
+ } \
+ while (_start < _shgroup->instance_count) { \
+ if (select_id) { \
+ GPU_select_load_id(select_id[_start]); \
+ }
+
+# define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(_start, _count) \
+ _start += _count; \
+ }
+
+#else
+# define GPU_SELECT_LOAD_IF_PICKSEL(select_id)
+# define GPU_SELECT_LOAD_IF_PICKSEL_CALL(call)
+# define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count)
+# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_shgroup, _start, _count) \
+ _start = 0; \
+ _count = _shgroup->interface.instance_count;
+
+#endif
+
+ /* Rendering Calls */
+ if (!ELEM(shgroup->type, DRW_SHG_NORMAL)) {
+ /* Replacing multiple calls with only one */
+ if (ELEM(shgroup->type, DRW_SHG_INSTANCE, DRW_SHG_INSTANCE_EXTERNAL)) {
+ if (shgroup->type == DRW_SHG_INSTANCE_EXTERNAL) {
+ if (shgroup->instance_geom != NULL) {
+ GPU_SELECT_LOAD_IF_PICKSEL(shgroup->override_selectid);
+ draw_geometry_prepare(shgroup, NULL);
+ draw_geometry_execute_ex(shgroup, shgroup->instance_geom, 0, 0, true);
+ }
+ }
+ else {
+ if (shgroup->instance_count > 0) {
+ unsigned int count, start;
+ draw_geometry_prepare(shgroup, NULL);
+ GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup, start, count)
+ {
+ draw_geometry_execute_ex(shgroup, shgroup->instance_geom, start, count, true);
+ }
+ GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count)
+ }
+ }
+ }
+ else { /* DRW_SHG_***_BATCH */
+ /* Some dynamic batch can have no geom (no call to aggregate) */
+ if (shgroup->instance_count > 0) {
+ unsigned int count, start;
+ draw_geometry_prepare(shgroup, NULL);
+ GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup, start, count)
+ {
+ draw_geometry_execute_ex(shgroup, shgroup->batch_geom, start, count, false);
+ }
+ GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count)
+ }
+ }
+ }
+ else {
+ bool prev_neg_scale = false;
+ for (DRWCall *call = shgroup->calls.first; call; call = call->next) {
+
+ /* OPTI/IDEA(clem): Do this preparation in another thread. */
+ draw_matrices_model_prepare(call->state);
+
+ if ((call->state->flag & DRW_CALL_CULLED) != 0)
+ continue;
+
+ /* Negative scale objects */
+ bool neg_scale = call->state->flag & DRW_CALL_NEGSCALE;
+ if (neg_scale != prev_neg_scale) {
+ glFrontFace((neg_scale) ? DST.backface : DST.frontface);
+ prev_neg_scale = neg_scale;
+ }
+
+ GPU_SELECT_LOAD_IF_PICKSEL_CALL(call);
+ draw_geometry_prepare(shgroup, call->state);
+
+ switch (call->type) {
+ case DRW_CALL_SINGLE:
+ draw_geometry_execute(shgroup, call->single.geometry);
+ break;
+ case DRW_CALL_INSTANCES:
+ draw_geometry_execute_ex(shgroup, call->instances.geometry, 0, *call->instances.count, true);
+ break;
+ case DRW_CALL_GENERATE:
+ call->generate.geometry_fn(shgroup, draw_geometry_execute, call->generate.user_data);
+ break;
+ default:
+ BLI_assert(0);
+ }
+ }
+ /* Reset state */
+ glFrontFace(DST.frontface);
+ }
+
+ /* TODO: remove, (currently causes alpha issue with sculpt, need to investigate) */
+ DRW_state_reset();
+}
+
+static void drw_update_view(void)
+{
+ if (DST.dirty_mat) {
+ DST.state_cache_id++;
+ DST.dirty_mat = false;
+
+ DRW_uniformbuffer_update(view_ubo, &DST.view_data);
+
+ /* Catch integer wrap around. */
+ if (UNLIKELY(DST.state_cache_id == 0)) {
+ DST.state_cache_id = 1;
+ /* We must reset all CallStates to ensure that not
+ * a single one stayed with cache_id equal to 1. */
+ BLI_mempool_iter iter;
+ DRWCallState *state;
+ BLI_mempool_iternew(DST.vmempool->states, &iter);
+ while ((state = BLI_mempool_iterstep(&iter))) {
+ state->cache_id = 0;
+ }
+ }
+
+ /* TODO dispatch threads to compute matrices/culling */
+ }
+
+ draw_clipping_setup_from_view();
+}
+
+static void drw_draw_pass_ex(DRWPass *pass, DRWShadingGroup *start_group, DRWShadingGroup *end_group)
+{
+ DST.shader = NULL;
+
+ BLI_assert(DST.buffer_finish_called && "DRW_render_instance_buffer_finish had not been called before drawing");
+
+ drw_update_view();
+
+ drw_state_set(pass->state);
+
+ DRW_stats_query_start(pass->name);
+
+ for (DRWShadingGroup *shgroup = start_group; shgroup; shgroup = shgroup->next) {
+ draw_shgroup(shgroup, pass->state);
+ /* break if upper limit */
+ if (shgroup == end_group) {
+ break;
+ }
+ }
+
+ /* Clear Bound textures */
+ for (int i = 0; i < GPU_max_textures(); i++) {
+ if (DST.RST.bound_texs[i] != NULL) {
+ GPU_texture_unbind(DST.RST.bound_texs[i]);
+ DST.RST.bound_texs[i] = NULL;
+ }
+ }
+
+ /* Clear Bound Ubos */
+ for (int i = 0; i < GPU_max_ubo_binds(); i++) {
+ if (DST.RST.bound_ubos[i] != NULL) {
+ GPU_uniformbuffer_unbind(DST.RST.bound_ubos[i]);
+ DST.RST.bound_ubos[i] = NULL;
+ }
+ }
+
+ if (DST.shader) {
+ GPU_shader_unbind();
+ DST.shader = NULL;
+ }
+
+ DRW_stats_query_end();
+}
+
+void DRW_draw_pass(DRWPass *pass)
+{
+ drw_draw_pass_ex(pass, pass->shgroups.first, pass->shgroups.last);
+}
+
+/* Draw only a subset of shgroups. Used in special situations as grease pencil strokes */
+void DRW_draw_pass_subset(DRWPass *pass, DRWShadingGroup *start_group, DRWShadingGroup *end_group)
+{
+ drw_draw_pass_ex(pass, start_group, end_group);
+}
+
+/** \} */
diff --git a/source/blender/draw/intern/draw_manager_profiling.c b/source/blender/draw/intern/draw_manager_profiling.c
index f9fbbac2e2e..d2ed22c57b7 100644
--- a/source/blender/draw/intern/draw_manager_profiling.c
+++ b/source/blender/draw/intern/draw_manager_profiling.c
@@ -32,7 +32,12 @@
#include "MEM_guardedalloc.h"
+#include "draw_manager.h"
+
#include "GPU_glew.h"
+#include "GPU_texture.h"
+
+#include "UI_resources.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -198,14 +203,127 @@ void DRW_stats_reset(void)
}
}
+static void draw_stat_5row(rcti *rect, int u, int v, const char *txt, const int size)
+{
+ BLF_draw_default_ascii(rect->xmin + (1 + u * 5) * U.widget_unit,
+ rect->ymax - (3 + v) * U.widget_unit, 0.0f,
+ txt, size);
+}
+
+static void draw_stat(rcti *rect, int u, int v, const char *txt, const int size)
+{
+ BLF_draw_default_ascii(rect->xmin + (1 + u) * U.widget_unit,
+ rect->ymax - (3 + v) * U.widget_unit, 0.0f,
+ txt, size);
+}
+
void DRW_stats_draw(rcti *rect)
{
char stat_string[64];
int lvl_index[MAX_NESTED_TIMER];
- int v = 0;
+ int v = 0, u = 0;
+
+ double init_tot_time = 0.0, background_tot_time = 0.0, render_tot_time = 0.0, tot_time = 0.0;
+
+ int fontid = BLF_default();
+ UI_FontThemeColor(fontid, TH_TEXT_HI);
+ BLF_enable(fontid, BLF_SHADOW);
+ BLF_shadow(fontid, 5, (const float[4]){0.0f, 0.0f, 0.0f, 0.75f});
+ BLF_shadow_offset(fontid, 0, -1);
+
+ BLF_batch_draw_begin();
+
+ /* ------------------------------------------ */
+ /* ---------------- CPU stats --------------- */
+ /* ------------------------------------------ */
+ /* Label row */
+ char col_label[32];
+ sprintf(col_label, "Engine");
+ draw_stat_5row(rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Init");
+ draw_stat_5row(rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Background");
+ draw_stat_5row(rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Render");
+ draw_stat_5row(rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Total (w/o cache)");
+ draw_stat_5row(rect, u++, v, col_label, sizeof(col_label));
+ v++;
+
+ /* Engines rows */
+ char time_to_txt[16];
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ u = 0;
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
+
+ draw_stat_5row(rect, u++, v, engine->idname, sizeof(engine->idname));
+
+ init_tot_time += data->init_time;
+ sprintf(time_to_txt, "%.2fms", data->init_time);
+ draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt));
+
+ background_tot_time += data->background_time;
+ sprintf(time_to_txt, "%.2fms", data->background_time);
+ draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt));
+
+ render_tot_time += data->render_time;
+ sprintf(time_to_txt, "%.2fms", data->render_time);
+ draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt));
+
+ tot_time += data->init_time + data->background_time + data->render_time;
+ sprintf(time_to_txt, "%.2fms", data->init_time + data->background_time + data->render_time);
+ draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ v++;
+ }
- BLI_snprintf(stat_string, sizeof(stat_string), "GPU Render Stats");
- BLF_draw_default_ascii(rect->xmin + 1 * U.widget_unit, rect->ymax - v++ * U.widget_unit, 0.0f, stat_string, sizeof(stat_string));
+ /* Totals row */
+ u = 0;
+ sprintf(col_label, "Sub Total");
+ draw_stat_5row(rect, u++, v, col_label, sizeof(col_label));
+ sprintf(time_to_txt, "%.2fms", init_tot_time);
+ draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ sprintf(time_to_txt, "%.2fms", background_tot_time);
+ draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ sprintf(time_to_txt, "%.2fms", render_tot_time);
+ draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ sprintf(time_to_txt, "%.2fms", tot_time);
+ draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ v += 2;
+
+ u = 0;
+ double *cache_time = GPU_viewport_cache_time_get(DST.viewport);
+ sprintf(col_label, "Cache Time");
+ draw_stat_5row(rect, u++, v, col_label, sizeof(col_label));
+ sprintf(time_to_txt, "%.2fms", *cache_time);
+ draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ v += 2;
+
+ /* ------------------------------------------ */
+ /* ---------------- GPU stats --------------- */
+ /* ------------------------------------------ */
+
+ /* Memory Stats */
+ unsigned int tex_mem = GPU_texture_memory_usage_get();
+ unsigned int vbo_mem = GWN_vertbuf_get_memory_usage();
+
+ sprintf(stat_string, "GPU Memory");
+ draw_stat(rect, 0, v, stat_string, sizeof(stat_string));
+ sprintf(stat_string, "%.2fMB", (double)(tex_mem + vbo_mem) / 1000000.0);
+ draw_stat_5row(rect, 1, v++, stat_string, sizeof(stat_string));
+ sprintf(stat_string, "Textures");
+ draw_stat(rect, 1, v, stat_string, sizeof(stat_string));
+ sprintf(stat_string, "%.2fMB", (double)tex_mem / 1000000.0);
+ draw_stat_5row(rect, 1, v++, stat_string, sizeof(stat_string));
+ sprintf(stat_string, "Meshes");
+ draw_stat(rect, 1, v, stat_string, sizeof(stat_string));
+ sprintf(stat_string, "%.2fMB", (double)vbo_mem / 1000000.0);
+ draw_stat_5row(rect, 1, v++, stat_string, sizeof(stat_string));
+ v += 1;
+
+ /* GPU Timings */
+ BLI_snprintf(stat_string, sizeof(stat_string), "GPU Render Timings");
+ draw_stat(rect, 0, v++, stat_string, sizeof(stat_string));
for (int i = 0; i < DTP.timer_increment; ++i) {
double time_ms, time_percent;
@@ -232,11 +350,14 @@ void DRW_stats_draw(rcti *rect)
time_percent = MIN2(time_percent, 100.0);
BLI_snprintf(stat_string, sizeof(stat_string), "%s", timer->name);
- BLF_draw_default_ascii(rect->xmin + (1 + timer->lvl) * U.widget_unit, rect->ymax - v * U.widget_unit, 0.0f, stat_string, sizeof(stat_string));
+ draw_stat(rect, 0 + timer->lvl, v, stat_string, sizeof(stat_string));
BLI_snprintf(stat_string, sizeof(stat_string), "%.2fms", time_ms);
- BLF_draw_default_ascii(rect->xmin + (13 + timer->lvl) * U.widget_unit, rect->ymax - v * U.widget_unit, 0.0f, stat_string, sizeof(stat_string));
+ draw_stat(rect, 12 + timer->lvl, v, stat_string, sizeof(stat_string));
BLI_snprintf(stat_string, sizeof(stat_string), "%.0f", time_percent);
- BLF_draw_default_ascii(rect->xmin + (17 + timer->lvl) * U.widget_unit, rect->ymax - v * U.widget_unit, 0.0f, stat_string, sizeof(stat_string));
+ draw_stat(rect, 16 + timer->lvl, v, stat_string, sizeof(stat_string));
v++;
}
-} \ No newline at end of file
+
+ BLF_batch_draw_end();
+ BLF_disable(fontid, BLF_SHADOW);
+}
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
new file mode 100644
index 00000000000..814109ee1e9
--- /dev/null
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -0,0 +1,387 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/intern/draw_manager_shader.c
+ * \ingroup draw
+ */
+
+#include "draw_manager.h"
+
+#include "DNA_world_types.h"
+#include "DNA_material_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_string_utils.h"
+#include "BLI_threads.h"
+#include "BLI_task.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "GPU_shader.h"
+#include "GPU_material.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+extern char datatoc_gpu_shader_2D_vert_glsl[];
+extern char datatoc_gpu_shader_3D_vert_glsl[];
+extern char datatoc_common_fullscreen_vert_glsl[];
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Deferred Compilation (DRW_deferred)
+ *
+ * Since compiling shader can take a long time, we do it in a non blocking
+ * manner in another thread.
+ *
+ * \{ */
+
+typedef struct DRWDeferredShader {
+ struct DRWDeferredShader *prev, *next;
+
+ GPUMaterial *mat;
+ char *vert, *geom, *frag, *defs;
+} DRWDeferredShader;
+
+typedef struct DRWShaderCompiler {
+ ListBase queue; /* DRWDeferredShader */
+ SpinLock list_lock;
+
+ DRWDeferredShader *mat_compiling;
+ ThreadMutex compilation_lock;
+
+ void *ogl_context;
+
+ int shaders_done; /* To compute progress. */
+} DRWShaderCompiler;
+
+static void drw_deferred_shader_free(DRWDeferredShader *dsh)
+{
+ /* Make sure it is not queued before freeing. */
+ MEM_SAFE_FREE(dsh->vert);
+ MEM_SAFE_FREE(dsh->geom);
+ MEM_SAFE_FREE(dsh->frag);
+ MEM_SAFE_FREE(dsh->defs);
+
+ MEM_freeN(dsh);
+}
+
+static void drw_deferred_shader_queue_free(ListBase *queue)
+{
+ DRWDeferredShader *dsh;
+ while((dsh = BLI_pophead(queue))) {
+ drw_deferred_shader_free(dsh);
+ }
+}
+
+static void drw_deferred_shader_compilation_exec(void *custom_data, short *stop, short *do_update, float *progress)
+{
+ DRWShaderCompiler *comp = (DRWShaderCompiler *)custom_data;
+ void *ogl_context = comp->ogl_context;
+
+ WM_opengl_context_activate(ogl_context);
+
+ while (true) {
+ BLI_spin_lock(&comp->list_lock);
+
+ if (*stop != 0) {
+ /* We don't want user to be able to cancel the compilation
+ * but wm can kill the task if we are closing blender. */
+ BLI_spin_unlock(&comp->list_lock);
+ break;
+ }
+
+ /* Pop tail because it will be less likely to lock the main thread
+ * if all GPUMaterials are to be freed (see DRW_deferred_shader_remove()). */
+ comp->mat_compiling = BLI_poptail(&comp->queue);
+ if (comp->mat_compiling == NULL) {
+ /* No more Shader to compile. */
+ BLI_spin_unlock(&comp->list_lock);
+ break;
+ }
+
+ comp->shaders_done++;
+ int total = BLI_listbase_count(&comp->queue) + comp->shaders_done;
+
+ BLI_mutex_lock(&comp->compilation_lock);
+ BLI_spin_unlock(&comp->list_lock);
+
+ /* Do the compilation. */
+ GPU_material_generate_pass(
+ comp->mat_compiling->mat,
+ comp->mat_compiling->vert,
+ comp->mat_compiling->geom,
+ comp->mat_compiling->frag,
+ comp->mat_compiling->defs);
+
+ *progress = (float)comp->shaders_done / (float)total;
+ *do_update = true;
+
+ glFlush();
+ BLI_mutex_unlock(&comp->compilation_lock);
+
+ drw_deferred_shader_free(comp->mat_compiling);
+ }
+
+ WM_opengl_context_release(ogl_context);
+}
+
+static void drw_deferred_shader_compilation_free(void *custom_data)
+{
+ DRWShaderCompiler *comp = (DRWShaderCompiler *)custom_data;
+
+ drw_deferred_shader_queue_free(&comp->queue);
+
+ BLI_spin_end(&comp->list_lock);
+ BLI_mutex_end(&comp->compilation_lock);
+
+ if (comp->ogl_context) {
+ /* Only destroy if the job owns the context. */
+ WM_opengl_context_dispose(comp->ogl_context);
+ }
+
+ MEM_freeN(comp);
+}
+
+static void drw_deferred_shader_add(
+ GPUMaterial *mat, const char *vert, const char *geom, const char *frag_lib, const char *defines)
+{
+ /* Do not deferre the compilation if we are rendering for image. */
+ if (DRW_state_is_image_render()) {
+ /* Double checking that this GPUMaterial is not going to be
+ * compiled by another thread. */
+ DRW_deferred_shader_remove(mat);
+ GPU_material_generate_pass(mat, vert, geom, frag_lib, defines);
+ return;
+ }
+
+ DRWDeferredShader *dsh = MEM_callocN(sizeof(DRWDeferredShader), "Deferred Shader");
+
+ dsh->mat = mat;
+ if (vert) dsh->vert = BLI_strdup(vert);
+ if (geom) dsh->geom = BLI_strdup(geom);
+ if (frag_lib) dsh->frag = BLI_strdup(frag_lib);
+ if (defines) dsh->defs = BLI_strdup(defines);
+
+ BLI_assert(DST.draw_ctx.evil_C);
+ wmWindowManager *wm = CTX_wm_manager(DST.draw_ctx.evil_C);
+ wmWindow *win = CTX_wm_window(DST.draw_ctx.evil_C);
+ Scene *scene = DST.draw_ctx.scene;
+
+ /* Get the running job or a new one if none is running. Can only have one job per type & owner. */
+ wmJob *wm_job = WM_jobs_get(wm, win, scene, "Shaders Compilation",
+ WM_JOB_PROGRESS | WM_JOB_SUSPEND, WM_JOB_TYPE_SHADER_COMPILATION);
+
+ DRWShaderCompiler *old_comp = (DRWShaderCompiler *)WM_jobs_customdata_get(wm_job);
+
+ DRWShaderCompiler *comp = MEM_callocN(sizeof(DRWShaderCompiler), "DRWShaderCompiler");
+ BLI_spin_init(&comp->list_lock);
+ BLI_mutex_init(&comp->compilation_lock);
+
+ if (old_comp) {
+ BLI_spin_lock(&old_comp->list_lock);
+ BLI_movelisttolist(&comp->queue, &old_comp->queue);
+ BLI_spin_unlock(&old_comp->list_lock);
+ /* Do not recreate context, just pass ownership. */
+ comp->ogl_context = old_comp->ogl_context;
+ old_comp->ogl_context = NULL;
+ }
+
+ BLI_addtail(&comp->queue, dsh);
+
+ /* Create only one context. */
+ if (comp->ogl_context == NULL) {
+ comp->ogl_context = WM_opengl_context_create();
+ WM_opengl_context_activate(DST.ogl_context);
+ }
+
+ WM_jobs_customdata_set(wm_job, comp, drw_deferred_shader_compilation_free);
+ WM_jobs_timer(wm_job, 0.1, NC_MATERIAL | ND_SHADING_DRAW, 0);
+ WM_jobs_callbacks(wm_job, drw_deferred_shader_compilation_exec, NULL, NULL, NULL);
+ WM_jobs_start(wm, wm_job);
+}
+
+void DRW_deferred_shader_remove(GPUMaterial *mat)
+{
+ Scene *scene = GPU_material_scene(mat);
+
+ for (wmWindowManager *wm = G.main->wm.first; wm; wm = wm->id.next) {
+ if (WM_jobs_test(wm, scene, WM_JOB_TYPE_SHADER_COMPILATION) == false) {
+ /* No job running, do not create a new one by calling WM_jobs_get. */
+ continue;
+ }
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ wmJob *wm_job = WM_jobs_get(wm, win, scene, "Shaders Compilation",
+ WM_JOB_PROGRESS | WM_JOB_SUSPEND, WM_JOB_TYPE_SHADER_COMPILATION);
+
+ DRWShaderCompiler *comp = (DRWShaderCompiler *)WM_jobs_customdata_get(wm_job);
+ if (comp != NULL) {
+ BLI_spin_lock(&comp->list_lock);
+ DRWDeferredShader *dsh;
+ dsh = (DRWDeferredShader *)BLI_findptr(&comp->queue, mat, offsetof(DRWDeferredShader, mat));
+ if (dsh) {
+ BLI_remlink(&comp->queue, dsh);
+ }
+
+ /* Wait for compilation to finish */
+ if (comp->mat_compiling != NULL) {
+ if (comp->mat_compiling->mat == mat) {
+ BLI_mutex_lock(&comp->compilation_lock);
+ BLI_mutex_unlock(&comp->compilation_lock);
+ }
+ }
+ BLI_spin_unlock(&comp->list_lock);
+
+ if (dsh) {
+ drw_deferred_shader_free(dsh);
+ }
+ }
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *frag, const char *defines)
+{
+ return GPU_shader_create(vert, frag, geom, NULL, defines);
+}
+
+GPUShader *DRW_shader_create_with_lib(
+ const char *vert, const char *geom, const char *frag, const char *lib, const char *defines)
+{
+ GPUShader *sh;
+ char *vert_with_lib = NULL;
+ char *frag_with_lib = NULL;
+ char *geom_with_lib = NULL;
+
+ vert_with_lib = BLI_string_joinN(lib, vert);
+ frag_with_lib = BLI_string_joinN(lib, frag);
+ if (geom) {
+ geom_with_lib = BLI_string_joinN(lib, geom);
+ }
+
+ sh = GPU_shader_create(vert_with_lib, frag_with_lib, geom_with_lib, NULL, defines);
+
+ MEM_freeN(vert_with_lib);
+ MEM_freeN(frag_with_lib);
+ if (geom) {
+ MEM_freeN(geom_with_lib);
+ }
+
+ return sh;
+}
+
+GPUShader *DRW_shader_create_2D(const char *frag, const char *defines)
+{
+ return GPU_shader_create(datatoc_gpu_shader_2D_vert_glsl, frag, NULL, NULL, defines);
+}
+
+GPUShader *DRW_shader_create_3D(const char *frag, const char *defines)
+{
+ return GPU_shader_create(datatoc_gpu_shader_3D_vert_glsl, frag, NULL, NULL, defines);
+}
+
+GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines)
+{
+ return GPU_shader_create(datatoc_common_fullscreen_vert_glsl, frag, NULL, NULL, defines);
+}
+
+GPUShader *DRW_shader_create_3D_depth_only(void)
+{
+ return GPU_shader_get_builtin_shader(GPU_SHADER_3D_DEPTH_ONLY);
+}
+
+GPUMaterial *DRW_shader_find_from_world(World *wo, const void *engine_type, int options)
+{
+ GPUMaterial *mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine_type, options);
+ if (DRW_state_is_image_render()) {
+ if (mat != NULL && GPU_material_status(mat) == GPU_MAT_QUEUED) {
+ /* XXX Hack : we return NULL so that the engine will call DRW_shader_create_from_XXX
+ * with the shader code and we will resume the compilation from there. */
+ return NULL;
+ }
+ }
+ return mat;
+}
+
+GPUMaterial *DRW_shader_find_from_material(Material *ma, const void *engine_type, int options)
+{
+ GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine_type, options);
+ if (DRW_state_is_image_render()) {
+ if (mat != NULL && GPU_material_status(mat) == GPU_MAT_QUEUED) {
+ /* XXX Hack : we return NULL so that the engine will call DRW_shader_create_from_XXX
+ * with the shader code and we will resume the compilation from there. */
+ return NULL;
+ }
+ }
+ return mat;
+}
+
+GPUMaterial *DRW_shader_create_from_world(
+ struct Scene *scene, World *wo, const void *engine_type, int options,
+ const char *vert, const char *geom, const char *frag_lib, const char *defines)
+{
+ GPUMaterial *mat = NULL;
+ if (DRW_state_is_image_render()) {
+ mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine_type, options);
+ }
+
+ if (mat == NULL) {
+ mat = GPU_material_from_nodetree(
+ scene, wo->nodetree, &wo->gpumaterial, engine_type, options,
+ vert, geom, frag_lib, defines, true);
+ }
+
+ drw_deferred_shader_add(mat, vert, geom, frag_lib, defines);
+
+ return mat;
+}
+
+GPUMaterial *DRW_shader_create_from_material(
+ struct Scene *scene, Material *ma, const void *engine_type, int options,
+ const char *vert, const char *geom, const char *frag_lib, const char *defines)
+{
+ GPUMaterial *mat = NULL;
+ if (DRW_state_is_image_render()) {
+ mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine_type, options);
+ }
+
+ if (mat == NULL) {
+ mat = GPU_material_from_nodetree(
+ scene, ma->nodetree, &ma->gpumaterial, engine_type, options,
+ vert, geom, frag_lib, defines, true);
+ }
+
+ drw_deferred_shader_add(mat, vert, geom, frag_lib, defines);
+
+ return mat;
+}
+
+void DRW_shader_free(GPUShader *shader)
+{
+ GPU_shader_free(shader);
+}
diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c
new file mode 100644
index 00000000000..65856a6bf5c
--- /dev/null
+++ b/source/blender/draw/intern/draw_manager_texture.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/intern/draw_manager_texture.c
+ * \ingroup draw
+ */
+
+#include "draw_manager.h"
+
+void drw_texture_get_format(
+ DRWTextureFormat format, bool is_framebuffer,
+ GPUTextureFormat *r_data_type, int *r_channels, bool *r_is_depth)
+{
+ /* Some formats do not work with framebuffers. */
+ if (is_framebuffer) {
+ switch (format) {
+ /* Only add formats that are COMPATIBLE with FB.
+ * Generally they are multiple of 16bit. */
+ case DRW_TEX_R_16:
+ case DRW_TEX_R_16I:
+ case DRW_TEX_R_32:
+ case DRW_TEX_RG_8:
+ case DRW_TEX_RG_16:
+ case DRW_TEX_RG_16I:
+ case DRW_TEX_RG_32:
+ case DRW_TEX_RGBA_8:
+ case DRW_TEX_RGBA_16:
+ case DRW_TEX_RGBA_32:
+ case DRW_TEX_DEPTH_16:
+ case DRW_TEX_DEPTH_24:
+ case DRW_TEX_DEPTH_24_STENCIL_8:
+ case DRW_TEX_DEPTH_32:
+ case DRW_TEX_RGB_11_11_10:
+ break;
+ default:
+ BLI_assert(false && "Texture format unsupported as render target!");
+ *r_channels = 4;
+ *r_data_type = GPU_RGBA8;
+ *r_is_depth = false;
+ return;
+ }
+ }
+
+ switch (format) {
+ case DRW_TEX_RGBA_8: *r_data_type = GPU_RGBA8; break;
+ case DRW_TEX_RGBA_16: *r_data_type = GPU_RGBA16F; break;
+ case DRW_TEX_RGBA_32: *r_data_type = GPU_RGBA32F; break;
+ case DRW_TEX_RGB_16: *r_data_type = GPU_RGB16F; break;
+ case DRW_TEX_RGB_11_11_10: *r_data_type = GPU_R11F_G11F_B10F; break;
+ case DRW_TEX_RG_8: *r_data_type = GPU_RG8; break;
+ case DRW_TEX_RG_16: *r_data_type = GPU_RG16F; break;
+ case DRW_TEX_RG_16I: *r_data_type = GPU_RG16I; break;
+ case DRW_TEX_RG_32: *r_data_type = GPU_RG32F; break;
+ case DRW_TEX_R_8: *r_data_type = GPU_R8; break;
+ case DRW_TEX_R_16: *r_data_type = GPU_R16F; break;
+ case DRW_TEX_R_16I: *r_data_type = GPU_R16I; break;
+ case DRW_TEX_R_32: *r_data_type = GPU_R32F; break;
+#if 0
+ case DRW_TEX_RGB_8: *r_data_type = GPU_RGB8; break;
+ case DRW_TEX_RGB_32: *r_data_type = GPU_RGB32F; break;
+#endif
+ case DRW_TEX_DEPTH_16: *r_data_type = GPU_DEPTH_COMPONENT16; break;
+ case DRW_TEX_DEPTH_24: *r_data_type = GPU_DEPTH_COMPONENT24; break;
+ case DRW_TEX_DEPTH_24_STENCIL_8: *r_data_type = GPU_DEPTH24_STENCIL8; break;
+ case DRW_TEX_DEPTH_32: *r_data_type = GPU_DEPTH_COMPONENT32F; break;
+ default :
+ /* file type not supported you must uncomment it from above */
+ BLI_assert(false);
+ break;
+ }
+
+ switch (format) {
+ case DRW_TEX_RGBA_8:
+ case DRW_TEX_RGBA_16:
+ case DRW_TEX_RGBA_32:
+ *r_channels = 4;
+ break;
+ case DRW_TEX_RGB_8:
+ case DRW_TEX_RGB_16:
+ case DRW_TEX_RGB_32:
+ case DRW_TEX_RGB_11_11_10:
+ *r_channels = 3;
+ break;
+ case DRW_TEX_RG_8:
+ case DRW_TEX_RG_16:
+ case DRW_TEX_RG_16I:
+ case DRW_TEX_RG_32:
+ *r_channels = 2;
+ break;
+ default:
+ *r_channels = 1;
+ break;
+ }
+
+ if (r_is_depth) {
+ *r_is_depth = ELEM(format, DRW_TEX_DEPTH_16, DRW_TEX_DEPTH_24, DRW_TEX_DEPTH_24_STENCIL_8);
+ }
+}
+
+void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags)
+{
+ GPU_texture_bind(tex, 0);
+ if (flags & DRW_TEX_MIPMAP) {
+ GPU_texture_mipmap_mode(tex, true, flags & DRW_TEX_FILTER);
+ GPU_texture_generate_mipmap(tex);
+ }
+ else {
+ GPU_texture_filter_mode(tex, flags & DRW_TEX_FILTER);
+ }
+ GPU_texture_wrap_mode(tex, flags & DRW_TEX_WRAP);
+ GPU_texture_compare_mode(tex, flags & DRW_TEX_COMPARE);
+ GPU_texture_unbind(tex);
+}
+
+GPUTexture *DRW_texture_create_1D(int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels)
+{
+ GPUTexture *tex;
+ GPUTextureFormat data_type;
+ int channels;
+
+ drw_texture_get_format(format, false, &data_type, &channels, NULL);
+ tex = GPU_texture_create_1D_custom(w, channels, data_type, fpixels, NULL);
+ drw_texture_set_parameters(tex, flags);
+
+ return tex;
+}
+
+GPUTexture *DRW_texture_create_2D(int w, int h, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels)
+{
+ GPUTexture *tex;
+ GPUTextureFormat data_type;
+ int channels;
+
+ drw_texture_get_format(format, false, &data_type, &channels, NULL);
+ tex = GPU_texture_create_2D_custom(w, h, channels, data_type, fpixels, NULL);
+ drw_texture_set_parameters(tex, flags);
+
+ return tex;
+}
+
+GPUTexture *DRW_texture_create_2D_array(
+ int w, int h, int d, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels)
+{
+ GPUTexture *tex;
+ GPUTextureFormat data_type;
+ int channels;
+
+ drw_texture_get_format(format, false, &data_type, &channels, NULL);
+ tex = GPU_texture_create_2D_array_custom(w, h, d, channels, data_type, fpixels, NULL);
+ drw_texture_set_parameters(tex, flags);
+
+ return tex;
+}
+
+GPUTexture *DRW_texture_create_3D(
+ int w, int h, int d, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels)
+{
+ GPUTexture *tex;
+ GPUTextureFormat data_type;
+ int channels;
+
+ drw_texture_get_format(format, false, &data_type, &channels, NULL);
+ tex = GPU_texture_create_3D_custom(w, h, d, channels, data_type, fpixels, NULL);
+ drw_texture_set_parameters(tex, flags);
+
+ return tex;
+}
+
+GPUTexture *DRW_texture_create_cube(int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels)
+{
+ GPUTexture *tex;
+ GPUTextureFormat data_type;
+ int channels;
+
+ drw_texture_get_format(format, false, &data_type, &channels, NULL);
+ tex = GPU_texture_create_cube_custom(w, channels, data_type, fpixels, NULL);
+ drw_texture_set_parameters(tex, flags);
+
+ return tex;
+}
+
+GPUTexture *DRW_texture_pool_query_2D(int w, int h, DRWTextureFormat format, DrawEngineType *engine_type)
+{
+ GPUTexture *tex;
+ GPUTextureFormat data_type;
+ int channels;
+
+ drw_texture_get_format(format, true, &data_type, &channels, NULL);
+ tex = GPU_viewport_texture_pool_query(DST.viewport, engine_type, w, h, channels, data_type);
+
+ return tex;
+}
+
+void DRW_texture_ensure_fullscreen_2D(GPUTexture **tex, DRWTextureFormat format, DRWTextureFlag flags)
+{
+ if (*(tex) == NULL) {
+ const float *size = DRW_viewport_size_get();
+ *(tex) = DRW_texture_create_2D((int)size[0], (int)size[1], format, flags, NULL);
+ }
+}
+
+void DRW_texture_ensure_2D(GPUTexture **tex, int w, int h, DRWTextureFormat format, DRWTextureFlag flags)
+{
+ if (*(tex) == NULL) {
+ *(tex) = DRW_texture_create_2D(w, h, format, flags, NULL);
+ }
+}
+
+void DRW_texture_generate_mipmaps(GPUTexture *tex)
+{
+ GPU_texture_bind(tex, 0);
+ GPU_texture_generate_mipmap(tex);
+ GPU_texture_unbind(tex);
+}
+
+void DRW_texture_free(GPUTexture *tex)
+{
+ GPU_texture_free(tex);
+}
diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c
index 391c29e511f..c65ed55561e 100644
--- a/source/blender/draw/intern/draw_view.c
+++ b/source/blender/draw/intern/draw_view.c
@@ -611,20 +611,20 @@ void DRW_draw_background(void)
/* **************************** 3D Cursor ******************************** */
-static bool is_cursor_visible(Scene *scene, ViewLayer *view_layer)
+static bool is_cursor_visible(const DRWContextState *draw_ctx, Scene *scene, ViewLayer *view_layer)
{
Object *ob = OBACT(view_layer);
/* don't draw cursor in paint modes, but with a few exceptions */
- if (ob && ob->mode & OB_MODE_ALL_PAINT) {
+ if (ob && draw_ctx->object_mode & OB_MODE_ALL_PAINT) {
/* exception: object is in weight paint and has deforming armature in pose mode */
- if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ if (draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) {
if (BKE_object_pose_armature_get(ob) != NULL) {
return true;
}
}
/* exception: object in texture paint mode, clone brush, use_clone_layer disabled */
- else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ else if (draw_ctx->object_mode & OB_MODE_TEXTURE_PAINT) {
const Paint *p = BKE_paint_get_active(scene, view_layer);
if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) {
@@ -645,7 +645,7 @@ void DRW_draw_cursor(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
- RegionView3D *rv3d = draw_ctx->rv3d;
+ ARegion *ar = draw_ctx->ar;
Scene *scene = draw_ctx->scene;
ViewLayer *view_layer = draw_ctx->view_layer;
@@ -654,62 +654,19 @@ void DRW_draw_cursor(void)
glDisable(GL_DEPTH_TEST);
glLineWidth(1.0f);
- if (is_cursor_visible(scene, view_layer)) {
- float *co = ED_view3d_cursor3d_get(scene, v3d);
- unsigned char crosshair_color[3];
-
- const float f5 = 0.25f;
- const float f10 = 0.5f;
- const float f20 = 1.0f;
-
- Gwn_VertFormat *format = immVertexFormat();
- unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
- unsigned int wpos = GWN_vertformat_attr_add(format, "world_pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ if (is_cursor_visible(draw_ctx, scene, view_layer)) {
+ int co[2];
+ if (ED_view3d_project_int_global(ar, ED_view3d_cursor3d_get(scene, v3d), co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- /* XXX Using instance shader without instance */
- immBindBuiltinProgram(GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR);
- immUniform1f("size", U.widget_unit);
- immUniform1f("pixel_size", *DRW_viewport_pixelsize_get());
- immUniformArray3fv("screen_vecs", DRW_viewport_screenvecs_get(), 2);
- immUniformMatrix4fv("ViewProjectionMatrix", rv3d->persmat);
+ ED_region_pixelspace(ar);
+ gpuTranslate2f(co[0], co[1]);
+ gpuScale2f(U.widget_unit, U.widget_unit);
- const int segments = 16;
-
- immBegin(GWN_PRIM_LINE_LOOP, segments);
- immAttrib3fv(wpos, co);
-
- for (int i = 0; i < segments; ++i) {
- float angle = (float)(2 * M_PI) * ((float)i / (float)segments);
- float x = f10 * cosf(angle);
- float y = f10 * sinf(angle);
-
- if (i % 2 == 0)
- immAttrib3ub(color, 255, 0, 0);
- else
- immAttrib3ub(color, 255, 255, 255);
-
- immVertex2f(pos, x, y);
+ Gwn_Batch *cursor_batch = DRW_cache_cursor_get();
+ GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_FLAT_COLOR);
+ GWN_batch_program_set(cursor_batch, GPU_shader_get_program(shader), GPU_shader_get_interface(shader));
+ GWN_batch_draw(cursor_batch);
}
- immEnd();
-
- UI_GetThemeColor3ubv(TH_VIEW_OVERLAY, crosshair_color);
-
- immBegin(GWN_PRIM_LINES, 8);
- immAttrib3ubv(color, crosshair_color);
- immAttrib3fv(wpos, co);
-
- immVertex2f(pos, -f20, 0);
- immVertex2f(pos, -f5, 0);
- immVertex2f(pos, +f5, 0);
- immVertex2f(pos, +f20, 0);
- immVertex2f(pos, 0, -f20);
- immVertex2f(pos, 0, -f5);
- immVertex2f(pos, 0, +f5);
- immVertex2f(pos, 0, +f20);
- immEnd();
-
- immUnbindProgram();
}
}
diff --git a/source/blender/draw/modes/edit_armature_mode.c b/source/blender/draw/modes/edit_armature_mode.c
index 4deb4f86692..3c0c33b1daa 100644
--- a/source/blender/draw/modes/edit_armature_mode.c
+++ b/source/blender/draw/modes/edit_armature_mode.c
@@ -154,4 +154,5 @@ DrawEngineType draw_engine_edit_armature_type = {
NULL,
&EDIT_ARMATURE_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c
index ec12f7570c2..73a4fb1e9e6 100644
--- a/source/blender/draw/modes/edit_curve_mode.c
+++ b/source/blender/draw/modes/edit_curve_mode.c
@@ -229,12 +229,11 @@ static void EDIT_CURVE_cache_populate(void *vedata, Object *ob)
EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
const Scene *scene = draw_ctx->scene;
- const Object *obedit = scene->obedit;
UNUSED_VARS(psl, stl);
if (ob->type == OB_CURVE) {
- if (ob == obedit) {
+ if (ob == draw_ctx->object_edit) {
Curve *cu = ob->data;
/* Get geometry cache */
struct Gwn_Batch *geom;
@@ -347,4 +346,5 @@ DrawEngineType draw_engine_edit_curve_type = {
NULL, /* draw_background but not needed by mode engines */
&EDIT_CURVE_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/edit_groom_mode.c b/source/blender/draw/modes/edit_groom_mode.c
index 3644fe16691..d12f918c0bc 100644
--- a/source/blender/draw/modes/edit_groom_mode.c
+++ b/source/blender/draw/modes/edit_groom_mode.c
@@ -195,7 +195,7 @@ static void EDIT_GROOM_cache_populate(void *vedata, Object *ob)
EDIT_GROOM_StorageList *stl = ((EDIT_GROOM_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- Object *obedit = scene->obedit;
+ Object *obedit = draw_ctx->object_edit;
GroomEditSettings *editsettings = &scene->toolsettings->groom_edit_settings;
UNUSED_VARS(psl);
diff --git a/source/blender/draw/modes/edit_lattice_mode.c b/source/blender/draw/modes/edit_lattice_mode.c
index ff4c557326e..0268f4eb453 100644
--- a/source/blender/draw/modes/edit_lattice_mode.c
+++ b/source/blender/draw/modes/edit_lattice_mode.c
@@ -188,13 +188,11 @@ static void EDIT_LATTICE_cache_populate(void *vedata, Object *ob)
EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl;
EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- Object *obedit = scene->obedit;
UNUSED_VARS(psl);
if (ob->type == OB_LATTICE) {
- if (ob == obedit) {
+ if (ob == draw_ctx->object_edit) {
/* Get geometry cache */
struct Gwn_Batch *geom;
@@ -294,4 +292,5 @@ DrawEngineType draw_engine_edit_lattice_type = {
NULL, /* draw_background but not needed by mode engines */
&EDIT_LATTICE_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c
index 1a8c03e3933..4bd69941809 100644
--- a/source/blender/draw/modes/edit_mesh_mode.c
+++ b/source/blender/draw/modes/edit_mesh_mode.c
@@ -137,15 +137,17 @@ static void EDIT_MESH_engine_init(void *vedata)
EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl;
const float *viewport_size = DRW_viewport_size_get();
+ const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
- DRWFboTexture tex[2] = {{
- &e_data.occlude_wire_depth_tx, DRW_TEX_DEPTH_24, DRW_TEX_TEMP},
- {&e_data.occlude_wire_color_tx, DRW_TEX_RGBA_8, DRW_TEX_FILTER | DRW_TEX_TEMP}
- };
- DRW_framebuffer_init(
- &fbl->occlude_wire_fb, &draw_engine_edit_mesh_type,
- (int)viewport_size[0], (int)viewport_size[1],
- tex, ARRAY_SIZE(tex));
+ e_data.occlude_wire_depth_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_DEPTH_24,
+ &draw_engine_edit_mesh_type);
+ e_data.occlude_wire_color_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_RGBA_8,
+ &draw_engine_edit_mesh_type);
+
+ GPU_framebuffer_ensure_config(&fbl->occlude_wire_fb, {
+ GPU_ATTACHMENT_TEXTURE(e_data.occlude_wire_depth_tx),
+ GPU_ATTACHMENT_TEXTURE(e_data.occlude_wire_color_tx)
+ });
if (!e_data.vcolor_face_shader) {
e_data.vcolor_face_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA);
@@ -406,9 +408,9 @@ static void EDIT_MESH_cache_init(void *vedata)
DRWShadingGroup *mix_shgrp = DRW_shgroup_create(e_data.overlay_mix_sh, psl->mix_occlude);
DRW_shgroup_call_add(mix_shgrp, quad, NULL);
DRW_shgroup_uniform_float(mix_shgrp, "alpha", &backwire_opacity, 1);
- DRW_shgroup_uniform_buffer(mix_shgrp, "wireColor", &e_data.occlude_wire_color_tx);
- DRW_shgroup_uniform_buffer(mix_shgrp, "wireDepth", &e_data.occlude_wire_depth_tx);
- DRW_shgroup_uniform_buffer(mix_shgrp, "sceneDepth", &dtxl->depth);
+ DRW_shgroup_uniform_texture_ref(mix_shgrp, "wireColor", &e_data.occlude_wire_color_tx);
+ DRW_shgroup_uniform_texture_ref(mix_shgrp, "wireDepth", &e_data.occlude_wire_depth_tx);
+ DRW_shgroup_uniform_texture_ref(mix_shgrp, "sceneDepth", &dtxl->depth);
}
}
@@ -443,11 +445,10 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
Scene *scene = draw_ctx->scene;
- Object *obedit = scene->obedit;
struct Gwn_Batch *geom;
if (ob->type == OB_MESH) {
- if (ob == obedit) {
+ if (ob == draw_ctx->object_edit) {
const Mesh *me = ob->data;
IDProperty *ces_mode_ed = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_EDIT, "");
bool do_occlude_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "show_occlude_wire");
@@ -524,7 +525,6 @@ static void EDIT_MESH_draw_scene(void *vedata)
EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl;
EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
DRW_draw_pass(psl->vcolor_faces);
@@ -535,29 +535,15 @@ static void EDIT_MESH_draw_scene(void *vedata)
/* render facefill */
DRW_draw_pass(psl->facefill_occlude);
- /* attach temp textures */
- DRW_framebuffer_texture_attach(fbl->occlude_wire_fb, e_data.occlude_wire_depth_tx, 0, 0);
- DRW_framebuffer_texture_attach(fbl->occlude_wire_fb, e_data.occlude_wire_color_tx, 0, 0);
-
/* Render wires on a separate framebuffer */
- DRW_framebuffer_bind(fbl->occlude_wire_fb);
- DRW_framebuffer_clear(true, true, false, clearcol, 1.0f);
+ GPU_framebuffer_bind(fbl->occlude_wire_fb);
+ GPU_framebuffer_clear_color_depth(fbl->occlude_wire_fb, clearcol, 1.0f);
DRW_draw_pass(psl->normals);
DRW_draw_pass(psl->edit_face_occluded);
- /* detach textures */
- DRW_framebuffer_texture_detach(dtxl->depth);
-
/* Combine with scene buffer */
- DRW_framebuffer_bind(dfbl->default_fb);
+ GPU_framebuffer_bind(dfbl->color_only_fb);
DRW_draw_pass(psl->mix_occlude);
-
- /* detach temp textures */
- DRW_framebuffer_texture_detach(e_data.occlude_wire_depth_tx);
- DRW_framebuffer_texture_detach(e_data.occlude_wire_color_tx);
-
- /* reattach */
- DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
}
else {
DRW_draw_pass(psl->normals);
@@ -610,4 +596,5 @@ DrawEngineType draw_engine_edit_mesh_type = {
NULL,
&EDIT_MESH_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/edit_metaball_mode.c b/source/blender/draw/modes/edit_metaball_mode.c
index a83f5ae33bc..bcabeef5bc3 100644
--- a/source/blender/draw/modes/edit_metaball_mode.c
+++ b/source/blender/draw/modes/edit_metaball_mode.c
@@ -119,11 +119,11 @@ static void EDIT_METABALL_cache_init(void *vedata)
psl->pass = DRW_pass_create("My Pass", state);
/* Create a shadingGroup using a function in draw_common.c or custom one */
- stl->g_data->group = shgroup_instance_mball_helpers(psl->pass, DRW_cache_screenspace_circle_get());
+ stl->g_data->group = shgroup_instance_mball_handles(psl->pass, DRW_cache_screenspace_circle_get());
}
}
-static void EDIT_METABALL_cache_populate_radius_visualization(
+static void EDIT_METABALL_cache_populate_radius(
DRWShadingGroup *group, MetaElem *ml, const float scale_xform[3][4],
const float *radius, const int selection_id)
{
@@ -142,7 +142,7 @@ static void EDIT_METABALL_cache_populate_radius_visualization(
DRW_shgroup_call_dynamic_add(group, scale_xform, radius, color);
}
-static void EDIT_METABALL_cache_populate_stiffness_visualization(
+static void EDIT_METABALL_cache_populate_stiffness(
DRWShadingGroup *group, MetaElem *ml, const float scale_xform[3][4],
const float *radius, const int selection_id)
{
@@ -169,11 +169,9 @@ static void EDIT_METABALL_cache_populate(void *vedata, Object *ob)
if (ob->type == OB_MBALL) {
const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- Object *obedit = scene->obedit;
DRWShadingGroup *group = stl->g_data->group;
- if (ob == obedit) {
+ if (ob == draw_ctx->object_edit) {
MetaBall *mb = ob->data;
const bool is_select = DRW_state_is_select();
@@ -181,13 +179,13 @@ static void EDIT_METABALL_cache_populate(void *vedata, Object *ob)
int selection_id = 0;
for (MetaElem *ml = mb->editelems->first; ml != NULL; ml = ml->next) {
- BKE_mball_element_calc_display_m3x4(ml->draw_scale_xform, ob->obmat, &ml->x);
+ BKE_mball_element_calc_scale_xform(ml->draw_scale_xform, ob->obmat, &ml->x);
ml->draw_stiffness_radius = ml->rad * atanf(ml->s) / (float)M_PI_2;
- EDIT_METABALL_cache_populate_radius_visualization(
+ EDIT_METABALL_cache_populate_radius(
group, ml, ml->draw_scale_xform, &ml->rad, is_select ? ++selection_id : -1);
- EDIT_METABALL_cache_populate_stiffness_visualization(
+ EDIT_METABALL_cache_populate_stiffness(
group, ml, ml->draw_scale_xform, &ml->draw_stiffness_radius, is_select ? ++selection_id : -1);
}
}
@@ -248,4 +246,5 @@ DrawEngineType draw_engine_edit_metaball_type = {
NULL, /* draw_background but not needed by mode engines */
&EDIT_METABALL_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/edit_surface_mode.c b/source/blender/draw/modes/edit_surface_mode.c
index 4e60c4abff5..8f0371925db 100644
--- a/source/blender/draw/modes/edit_surface_mode.c
+++ b/source/blender/draw/modes/edit_surface_mode.c
@@ -266,4 +266,5 @@ DrawEngineType draw_engine_edit_surface_type = {
NULL, /* draw_background but not needed by mode engines */
&EDIT_SURFACE_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/edit_text_mode.c b/source/blender/draw/modes/edit_text_mode.c
index b375bad84b5..43c4a356279 100644
--- a/source/blender/draw/modes/edit_text_mode.c
+++ b/source/blender/draw/modes/edit_text_mode.c
@@ -190,13 +190,11 @@ static void EDIT_TEXT_cache_populate(void *vedata, Object *ob)
EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl;
EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- Object *obedit = scene->obedit;
UNUSED_VARS(psl, stl);
if (ob->type == OB_FONT) {
- if (ob == obedit) {
+ if (ob == draw_ctx->object_edit) {
const Curve *cu = ob->data;
/* Get geometry cache */
struct Gwn_Batch *geom;
@@ -309,4 +307,5 @@ DrawEngineType draw_engine_edit_text_type = {
NULL, /* draw_background but not needed by mode engines */
&EDIT_TEXT_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index 091edf10435..52db4092fbc 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -34,7 +34,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
#include "DNA_modifier_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_lightprobe_types.h"
#include "DNA_particle_types.h"
#include "DNA_view3d_types.h"
@@ -59,6 +59,8 @@
#include "GPU_shader.h"
#include "GPU_texture.h"
+#include "MEM_guardedalloc.h"
+
#include "UI_resources.h"
#include "draw_mode_engines.h"
@@ -80,12 +82,12 @@ extern char datatoc_object_empty_image_frag_glsl[];
extern char datatoc_object_empty_image_vert_glsl[];
extern char datatoc_object_lightprobe_grid_vert_glsl[];
extern char datatoc_object_particle_prim_vert_glsl[];
-extern char datatoc_object_particle_prim_frag_glsl[];
extern char datatoc_object_particle_dot_vert_glsl[];
extern char datatoc_object_particle_dot_frag_glsl[];
extern char datatoc_common_globals_lib_glsl[];
extern char datatoc_common_fxaa_lib_glsl[];
-extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
+extern char datatoc_gpu_shader_flat_color_frag_glsl[];
+extern char datatoc_common_fullscreen_vert_glsl[];
extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
/* *********** LISTS *********** */
@@ -109,8 +111,9 @@ typedef struct OBJECT_PassList {
} OBJECT_PassList;
typedef struct OBJECT_FramebufferList {
- struct GPUFrameBuffer *outlines;
- struct GPUFrameBuffer *blur;
+ struct GPUFrameBuffer *outlines_fb;
+ struct GPUFrameBuffer *blur_fb;
+ struct GPUFrameBuffer *expand_fb;
} OBJECT_FramebufferList;
typedef struct OBJECT_StorageList {
@@ -159,7 +162,7 @@ typedef struct OBJECT_PrivateData {
DRWShadingGroup *probe_grid;
/* MetaBalls */
- DRWShadingGroup *mball_circle;
+ DRWShadingGroup *mball_handle;
/* Lamps */
DRWShadingGroup *lamp_center;
@@ -218,12 +221,25 @@ typedef struct OBJECT_PrivateData {
DRWShadingGroup *wire_select_group;
DRWShadingGroup *wire_transform;
+ /* Points */
+ DRWShadingGroup *points;
+ DRWShadingGroup *points_active;
+ DRWShadingGroup *points_active_group;
+ DRWShadingGroup *points_select;
+ DRWShadingGroup *points_select_group;
+ DRWShadingGroup *points_transform;
+
/* Hair Systems */
DRWShadingGroup *hair_verts;
DRWShadingGroup *hair_edges;
} OBJECT_PrivateData; /* Transient data */
static struct {
+ /* Instance Data format */
+ struct Gwn_VertFormat *particle_format;
+ struct Gwn_VertFormat *empty_image_format;
+ struct Gwn_VertFormat *empty_image_wire_format;
+
/* fullscreen shaders */
GPUShader *outline_resolve_sh;
GPUShader *outline_resolve_aa_sh;
@@ -276,23 +292,31 @@ static void OBJECT_engine_init(void *vedata)
OBJECT_FramebufferList *fbl = ((OBJECT_Data *)vedata)->fbl;
const float *viewport_size = DRW_viewport_size_get();
+ const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
if (DRW_state_is_fbo()) {
- DRWFboTexture tex[2] = {
- {&e_data.outlines_depth_tx, DRW_TEX_DEPTH_24, DRW_TEX_TEMP},
- {&e_data.outlines_color_tx, DRW_TEX_RGBA_8, DRW_TEX_FILTER | DRW_TEX_TEMP},
- };
+ e_data.outlines_depth_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_DEPTH_24,
+ &draw_engine_object_type);
+ e_data.outlines_color_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_RGBA_8,
+ &draw_engine_object_type);
+
+ GPU_framebuffer_ensure_config(&fbl->outlines_fb, {
+ GPU_ATTACHMENT_TEXTURE(e_data.outlines_depth_tx),
+ GPU_ATTACHMENT_TEXTURE(e_data.outlines_color_tx)
+ });
- DRW_framebuffer_init(
- &fbl->outlines, &draw_engine_object_type,
- (int)viewport_size[0], (int)viewport_size[1],
- tex, 2);
+ GPU_framebuffer_ensure_config(&fbl->expand_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(e_data.outlines_color_tx)
+ });
- DRWFboTexture blur_tex = {&e_data.outlines_blur_tx, DRW_TEX_RGBA_8, DRW_TEX_FILTER | DRW_TEX_TEMP};
- DRW_framebuffer_init(
- &fbl->blur, &draw_engine_object_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &blur_tex, 1);
+ e_data.outlines_blur_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_RGBA_8,
+ &draw_engine_object_type);
+
+ GPU_framebuffer_ensure_config(&fbl->blur_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(e_data.outlines_blur_tx)
+ });
}
if (!e_data.outline_resolve_sh) {
@@ -301,7 +325,7 @@ static void OBJECT_engine_init(void *vedata)
if (!e_data.outline_resolve_aa_sh) {
e_data.outline_resolve_aa_sh = DRW_shader_create_with_lib(
- datatoc_gpu_shader_fullscreen_vert_glsl, NULL,
+ datatoc_common_fullscreen_vert_glsl, NULL,
datatoc_object_outline_resolve_frag_glsl,
datatoc_common_fxaa_lib_glsl,
"#define FXAA_ALPHA\n"
@@ -340,12 +364,12 @@ static void OBJECT_engine_init(void *vedata)
if (!e_data.part_prim_sh) {
e_data.part_prim_sh = DRW_shader_create(
- datatoc_object_particle_prim_vert_glsl, NULL, datatoc_object_particle_prim_frag_glsl, NULL);
+ datatoc_object_particle_prim_vert_glsl, NULL, datatoc_gpu_shader_flat_color_frag_glsl, NULL);
}
if (!e_data.part_axis_sh) {
e_data.part_axis_sh = DRW_shader_create(
- datatoc_object_particle_prim_vert_glsl, NULL, datatoc_object_particle_prim_frag_glsl,
+ datatoc_object_particle_prim_vert_glsl, NULL, datatoc_gpu_shader_flat_color_frag_glsl,
"#define USE_AXIS\n");
}
@@ -540,6 +564,9 @@ static void OBJECT_engine_init(void *vedata)
static void OBJECT_engine_free(void)
{
+ MEM_SAFE_FREE(e_data.particle_format);
+ MEM_SAFE_FREE(e_data.empty_image_format);
+ MEM_SAFE_FREE(e_data.empty_image_wire_format);
DRW_SHADER_FREE_SAFE(e_data.outline_resolve_sh);
DRW_SHADER_FREE_SAFE(e_data.outline_resolve_aa_sh);
DRW_SHADER_FREE_SAFE(e_data.outline_detect_sh);
@@ -570,6 +597,15 @@ static DRWShadingGroup *shgroup_wire(DRWPass *pass, const float col[4], GPUShade
return grp;
}
+/* currently same as 'shgroup_outline', new function to avoid confustion */
+static DRWShadingGroup *shgroup_points(DRWPass *pass, const float col[4], GPUShader *sh)
+{
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_vec4(grp, "color", col, 1);
+
+ return grp;
+}
+
static DRWShadingGroup *shgroup_theme_id_to_outline_or(
OBJECT_StorageList *stl, int theme_id, DRWShadingGroup *fallback)
{
@@ -604,6 +640,23 @@ static DRWShadingGroup *shgroup_theme_id_to_wire_or(
}
}
+static DRWShadingGroup *shgroup_theme_id_to_point_or(
+ OBJECT_StorageList *stl, int theme_id, DRWShadingGroup *fallback)
+{
+ switch (theme_id) {
+ case TH_ACTIVE:
+ return stl->g_data->points_active;
+ case TH_SELECT:
+ return stl->g_data->points_select;
+ case TH_GROUP_ACTIVE:
+ return stl->g_data->points_select_group;
+ case TH_TRANSFORM:
+ return stl->g_data->points_transform;
+ default:
+ return fallback;
+ }
+}
+
static void image_calc_aspect(Image *ima, ImageUser *iuser, float r_image_aspect[2])
{
float ima_x, ima_y;
@@ -672,14 +725,16 @@ static void DRW_shgroup_empty_image(
image_calc_aspect(ob->data, ob->iuser, empty_image_data->image_aspect);
if (tex) {
+ DRW_shgroup_instance_format(e_data.empty_image_format, {
+ {"objectColor" , DRW_ATTRIB_FLOAT, 4},
+ {"size" , DRW_ATTRIB_FLOAT, 1},
+ {"offset" , DRW_ATTRIB_FLOAT, 2},
+ {"InstanceModelMatrix" , DRW_ATTRIB_FLOAT, 16},
+ });
+
struct Gwn_Batch *geom = DRW_cache_image_plane_get();
DRWShadingGroup *grp = DRW_shgroup_instance_create(
- e_data.object_empty_image_sh, psl->non_meshes, geom);
- DRW_shgroup_attrib_float(grp, "objectColor", 4);
- DRW_shgroup_attrib_float(grp, "size", 1);
- DRW_shgroup_attrib_float(grp, "offset", 2);
- DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
-
+ e_data.object_empty_image_sh, psl->non_meshes, geom, e_data.empty_image_format);
DRW_shgroup_uniform_texture(grp, "image", tex);
DRW_shgroup_uniform_vec2(grp, "aspect", empty_image_data->image_aspect, 1);
@@ -690,14 +745,16 @@ static void DRW_shgroup_empty_image(
}
{
+ DRW_shgroup_instance_format(e_data.empty_image_wire_format, {
+ {"objectColor" , DRW_ATTRIB_FLOAT, 4},
+ {"size" , DRW_ATTRIB_FLOAT, 1},
+ {"offset" , DRW_ATTRIB_FLOAT, 2},
+ {"InstanceModelMatrix" , DRW_ATTRIB_FLOAT, 16}
+ });
+
struct Gwn_Batch *geom = DRW_cache_image_plane_wire_get();
DRWShadingGroup *grp = DRW_shgroup_instance_create(
- e_data.object_empty_image_wire_sh, psl->non_meshes, geom);
- DRW_shgroup_attrib_float(grp, "color", 3);
- DRW_shgroup_attrib_float(grp, "size", 1);
- DRW_shgroup_attrib_float(grp, "offset", 2);
- DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
-
+ e_data.object_empty_image_wire_sh, psl->non_meshes, geom, e_data.empty_image_wire_format);
DRW_shgroup_uniform_vec2(grp, "aspect", empty_image_data->image_aspect, 1);
empty_image_data->shgrp_wire = grp;
@@ -774,23 +831,23 @@ static void OBJECT_cache_init(void *vedata)
psl->outlines_search = DRW_pass_create("Outlines Detect Pass", state);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_detect_sh, psl->outlines_search);
- DRW_shgroup_uniform_buffer(grp, "outlineColor", &e_data.outlines_color_tx);
- DRW_shgroup_uniform_buffer(grp, "outlineDepth", &e_data.outlines_depth_tx);
- DRW_shgroup_uniform_buffer(grp, "sceneDepth", &dtxl->depth);
+ DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &e_data.outlines_color_tx);
+ DRW_shgroup_uniform_texture_ref(grp, "outlineDepth", &e_data.outlines_depth_tx);
+ DRW_shgroup_uniform_texture_ref(grp, "sceneDepth", &dtxl->depth);
DRW_shgroup_uniform_float(grp, "alphaOcclu", &alphaOcclu, 1);
DRW_shgroup_call_add(grp, quad, NULL);
psl->outlines_expand = DRW_pass_create("Outlines Expand Pass", state);
grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_expand);
- DRW_shgroup_uniform_buffer(grp, "outlineColor", &e_data.outlines_blur_tx);
+ DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &e_data.outlines_blur_tx);
DRW_shgroup_uniform_bool(grp, "doExpand", &bTrue, 1);
DRW_shgroup_call_add(grp, quad, NULL);
psl->outlines_bleed = DRW_pass_create("Outlines Bleed Pass", state);
grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_bleed);
- DRW_shgroup_uniform_buffer(grp, "outlineColor", &e_data.outlines_color_tx);
+ DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &e_data.outlines_color_tx);
DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1);
DRW_shgroup_call_add(grp, quad, NULL);
}
@@ -802,7 +859,7 @@ static void OBJECT_cache_init(void *vedata)
struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_resolve_aa_sh, psl->outlines_resolve);
- DRW_shgroup_uniform_buffer(grp, "outlineBluredColor", &e_data.outlines_blur_tx);
+ DRW_shgroup_uniform_texture_ref(grp, "outlineBluredColor", &e_data.outlines_blur_tx);
DRW_shgroup_uniform_vec2(grp, "rcpDimensions", e_data.inv_viewport_size, 1);
DRW_shgroup_call_add(grp, quad, NULL);
}
@@ -827,7 +884,7 @@ static void OBJECT_cache_init(void *vedata)
DRW_shgroup_uniform_float(grp, "gridOneOverLogSubdiv", &e_data.grid_settings[4], 1);
DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo);
DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_call_add(grp, quad, mat);
grp = DRW_shgroup_create(e_data.grid_sh, psl->grid);
@@ -835,7 +892,7 @@ static void OBJECT_cache_init(void *vedata)
DRW_shgroup_uniform_vec3(grp, "planeNormal", e_data.grid_normal, 1);
DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.grid_axes, 1);
DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_call_add(grp, quad, mat);
grp = DRW_shgroup_create(e_data.grid_sh, psl->grid);
@@ -843,7 +900,7 @@ static void OBJECT_cache_init(void *vedata)
DRW_shgroup_uniform_vec3(grp, "planeNormal", e_data.zplane_normal, 1);
DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1);
DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_call_add(grp, quad, mat);
}
@@ -976,11 +1033,30 @@ static void OBJECT_cache_init(void *vedata)
stl->g_data->wire_active_group = shgroup_wire(psl->non_meshes, ts.colorGroupActive, sh);
}
+
+ {
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR);
+
+ /* Unselected */
+ stl->g_data->points = shgroup_points(psl->non_meshes, ts.colorWire, sh);
+
+ /* Select */
+ stl->g_data->points_select = shgroup_points(psl->non_meshes, ts.colorSelect, sh);
+ stl->g_data->points_select_group = shgroup_points(psl->non_meshes, ts.colorGroupActive, sh);
+
+ /* Transform */
+ stl->g_data->points_transform = shgroup_points(psl->non_meshes, ts.colorTransform, sh);
+
+ /* Active */
+ stl->g_data->points_active = shgroup_points(psl->non_meshes, ts.colorActive, sh);
+ stl->g_data->points_active_group = shgroup_points(psl->non_meshes, ts.colorGroupActive, sh);
+ }
+
{
- /* Metaballs Helpers */
+ /* Metaballs Handles */
struct Gwn_Batch *geom;
geom = DRW_cache_screenspace_circle_get();
- stl->g_data->mball_circle = shgroup_instance_mball_helpers(psl->non_meshes, geom);
+ stl->g_data->mball_handle = shgroup_instance_mball_handles(psl->non_meshes, geom);
}
{
@@ -1130,7 +1206,7 @@ static void OBJECT_cache_init(void *vedata)
}
}
-static void DRW_shgroup_mball_helpers(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer)
+static void DRW_shgroup_mball_handles(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer)
{
MetaBall *mb = ob->data;
@@ -1139,8 +1215,8 @@ static void DRW_shgroup_mball_helpers(OBJECT_StorageList *stl, Object *ob, ViewL
for (MetaElem *ml = mb->elems.first; ml != NULL; ml = ml->next) {
/* draw radius */
- BKE_mball_element_calc_display_m3x4(ml->draw_scale_xform, ob->obmat, &ml->x);
- DRW_shgroup_call_dynamic_add(stl->g_data->mball_circle, ml->draw_scale_xform, &ml->rad, color);
+ BKE_mball_element_calc_scale_xform(ml->draw_scale_xform, ob->obmat, &ml->x);
+ DRW_shgroup_call_dynamic_add(stl->g_data->mball_handle, ml->draw_scale_xform, &ml->rad, color);
}
}
@@ -1151,15 +1227,22 @@ static void DRW_shgroup_lamp(OBJECT_StorageList *stl, Object *ob, ViewLayer *vie
int theme_id = DRW_object_wire_theme_get(ob, view_layer, &color);
static float zero = 0.0f;
- float **la_mats = (float **)DRW_object_engine_data_ensure(ob, &draw_engine_object_type, NULL);
- if (*la_mats == NULL) {
- /* we need 2 matrices */
- *la_mats = MEM_mallocN(sizeof(float) * 16 * 2, "Lamp Object Mode Matrices");
- }
+ typedef struct LampEngineData {
+ ObjectEngineData engine_data;
+ float shape_mat[4][4];
+ float spot_blend_mat[4][4];
+ } LampEngineData;
- float (*shapemat)[4], (*spotblendmat)[4];
- shapemat = (float (*)[4])(*la_mats);
- spotblendmat = (float (*)[4])(*la_mats + 16);
+ LampEngineData *lamp_engine_data =
+ (LampEngineData *)DRW_object_engine_data_ensure(
+ ob,
+ &draw_engine_object_type,
+ sizeof(LampEngineData),
+ NULL,
+ NULL);
+
+ float (*shapemat)[4] = lamp_engine_data->shape_mat;
+ float (*spotblendmat)[4] = lamp_engine_data->spot_blend_mat;
/* Don't draw the center if it's selected or active */
if (theme_id == TH_GROUP)
@@ -1257,7 +1340,8 @@ static void DRW_shgroup_camera(OBJECT_StorageList *stl, Object *ob, ViewLayer *v
RegionView3D *rv3d = draw_ctx->rv3d;
Camera *cam = ob->data;
- const bool is_active = (ob == v3d->camera);
+ const Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera);
+ const bool is_active = (ob == camera_object);
const bool look_through = (is_active && (rv3d->persp == RV3D_CAMOB));
float *color;
DRW_object_wire_theme_get(ob, view_layer, &color);
@@ -1491,6 +1575,8 @@ static void DRW_shgroup_speaker(OBJECT_StorageList *stl, Object *ob, ViewLayer *
}
typedef struct OBJECT_LightProbeEngineData {
+ ObjectEngineData engine_data;
+
float prb_mats[6][4][4];
float probe_cube_mat[4][4];
float draw_size;
@@ -1498,6 +1584,7 @@ typedef struct OBJECT_LightProbeEngineData {
float increment_y[3];
float increment_z[3];
float corner[3];
+ unsigned int cell_count;
} OBJECT_LightProbeEngineData;
static void DRW_shgroup_lightprobe(OBJECT_StorageList *stl, OBJECT_PassList *psl, Object *ob, ViewLayer *view_layer)
@@ -1508,13 +1595,13 @@ static void DRW_shgroup_lightprobe(OBJECT_StorageList *stl, OBJECT_PassList *psl
bool do_outlines = ((ob->base_flag & BASE_SELECTED) != 0);
DRW_object_wire_theme_get(ob, view_layer, &color);
- OBJECT_LightProbeEngineData *prb_data;
- OBJECT_LightProbeEngineData **prb_data_pt = (OBJECT_LightProbeEngineData **)DRW_object_engine_data_ensure(ob, &draw_engine_object_type, NULL);
- if (*prb_data_pt == NULL) {
- *prb_data_pt = MEM_mallocN(sizeof(OBJECT_LightProbeEngineData), "Probe Clip distances Matrices");
- }
-
- prb_data = *prb_data_pt;
+ OBJECT_LightProbeEngineData *prb_data =
+ (OBJECT_LightProbeEngineData *)DRW_object_engine_data_ensure(
+ ob,
+ &draw_engine_object_type,
+ sizeof(OBJECT_LightProbeEngineData),
+ NULL,
+ NULL);
if ((DRW_state_is_select() || do_outlines) && ((prb->flag & LIGHTPROBE_FLAG_SHOW_DATA) != 0)) {
@@ -1551,8 +1638,8 @@ static void DRW_shgroup_lightprobe(OBJECT_StorageList *stl, OBJECT_PassList *psl
mul_m4_v3(ob->obmat, prb_data->increment_z);
sub_v3_v3(prb_data->increment_z, prb_data->corner);
- DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.lightprobe_grid_sh, psl->lightprobes, DRW_cache_sphere_get());
- DRW_shgroup_set_instance_count(grp, prb->grid_resolution_x * prb->grid_resolution_y * prb->grid_resolution_z);
+ prb_data->cell_count = prb->grid_resolution_x * prb->grid_resolution_y * prb->grid_resolution_z;
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.lightprobe_grid_sh, psl->lightprobes);
DRW_shgroup_uniform_vec4(grp, "color", color, 1);
DRW_shgroup_uniform_vec3(grp, "corner", prb_data->corner, 1);
DRW_shgroup_uniform_vec3(grp, "increment_x", prb_data->increment_x, 1);
@@ -1560,6 +1647,7 @@ static void DRW_shgroup_lightprobe(OBJECT_StorageList *stl, OBJECT_PassList *psl
DRW_shgroup_uniform_vec3(grp, "increment_z", prb_data->increment_z, 1);
DRW_shgroup_uniform_ivec3(grp, "grid_resolution", &prb->grid_resolution_x, 1);
DRW_shgroup_uniform_float(grp, "sphere_size", &prb->data_draw_size, 1);
+ DRW_shgroup_call_instances_add(grp, DRW_cache_sphere_get(), NULL, &prb_data->cell_count);
}
else if (prb->type == LIGHTPROBE_TYPE_CUBE) {
prb_data->draw_size = prb->data_draw_size * 0.1f;
@@ -1751,12 +1839,15 @@ static void OBJECT_cache_populate_particles(Object *ob,
unit_m4(mat);
if (draw_as != PART_DRAW_PATH) {
- struct Gwn_Batch *geom = DRW_cache_particles_get_dots(psys);
+ struct Gwn_Batch *geom = DRW_cache_particles_get_dots(ob, psys);
DRWShadingGroup *shgrp = NULL;
static int screen_space[2] = {0, 1};
static float def_prim_col[3] = {0.5f, 0.5f, 0.5f};
static float def_sec_col[3] = {1.0f, 1.0f, 1.0f};
+ /* Dummy particle format for instancing to work. */
+ DRW_shgroup_instance_format(e_data.particle_format, {{"dummy", DRW_ATTRIB_FLOAT, 1}});
+
Material *ma = give_current_material(ob, part->omat);
switch (draw_as) {
@@ -1771,21 +1862,24 @@ static void OBJECT_cache_populate_particles(Object *ob,
break;
case PART_DRAW_CROSS:
shgrp = DRW_shgroup_instance_create(
- e_data.part_prim_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_CROSS));
+ e_data.part_prim_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_CROSS),
+ e_data.particle_format);
DRW_shgroup_uniform_texture(shgrp, "ramp", globals_ramp);
DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1);
DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[0], 1);
break;
case PART_DRAW_CIRC:
shgrp = DRW_shgroup_instance_create(
- e_data.part_prim_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_CIRC));
+ e_data.part_prim_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_CIRC),
+ e_data.particle_format);
DRW_shgroup_uniform_texture(shgrp, "ramp", globals_ramp);
DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1);
DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[1], 1);
break;
case PART_DRAW_AXIS:
shgrp = DRW_shgroup_instance_create(
- e_data.part_axis_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_AXIS));
+ e_data.part_axis_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_AXIS),
+ e_data.particle_format);
DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[0], 1);
break;
default:
@@ -1808,7 +1902,6 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl;
OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
ViewLayer *view_layer = draw_ctx->view_layer;
View3D *v3d = draw_ctx->v3d;
int theme_id = TH_UNDEFINED;
@@ -1828,14 +1921,13 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
bool do_outlines = ((ob->base_flag & BASE_SELECTED) != 0);
if (do_outlines) {
- Object *obedit = scene->obedit;
- if (ob != obedit && !((ob == draw_ctx->obact) && (ob->mode & OB_MODE_ALL_PAINT))) {
+ if ((ob != draw_ctx->object_edit) && !((ob == draw_ctx->obact) && (draw_ctx->object_mode & OB_MODE_ALL_PAINT))) {
struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
DRWShadingGroup *shgroup = shgroup_theme_id_to_outline_or(stl, theme_id, NULL);
if (shgroup != NULL) {
- DRW_shgroup_call_add(shgroup, geom, ob->obmat);
+ DRW_shgroup_call_object_add(shgroup, geom, ob);
}
}
}
@@ -1844,18 +1936,30 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
switch (ob->type) {
case OB_MESH:
{
- Mesh *me = ob->data;
- if (me->totpoly == 0) {
- Object *obedit = scene->obedit;
- if (ob != obedit) {
- struct Gwn_Batch *geom = DRW_cache_mesh_edges_get(ob);
- if (geom) {
- if (theme_id == TH_UNDEFINED) {
- theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ if (ob != draw_ctx->object_edit) {
+ Mesh *me = ob->data;
+ if (me->totpoly == 0) {
+ if (me->totedge == 0) {
+ struct Gwn_Batch *geom = DRW_cache_mesh_verts_get(ob);
+ if (geom) {
+ if (theme_id == TH_UNDEFINED) {
+ theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ }
+
+ DRWShadingGroup *shgroup = shgroup_theme_id_to_point_or(stl, theme_id, stl->g_data->points);
+ DRW_shgroup_call_object_add(shgroup, geom, ob);
+ }
+ }
+ else {
+ struct Gwn_Batch *geom = DRW_cache_mesh_edges_get(ob);
+ if (geom) {
+ if (theme_id == TH_UNDEFINED) {
+ theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ }
+
+ DRWShadingGroup *shgroup = shgroup_theme_id_to_wire_or(stl, theme_id, stl->g_data->wire);
+ DRW_shgroup_call_object_add(shgroup, geom, ob);
}
-
- DRWShadingGroup *shgroup = shgroup_theme_id_to_wire_or(stl, theme_id, stl->g_data->wire);
- DRW_shgroup_call_add(shgroup, geom, ob->obmat);
}
}
}
@@ -1865,44 +1969,40 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
break;
case OB_LATTICE:
{
- Object *obedit = scene->obedit;
- if (ob != obedit) {
+ if (ob != draw_ctx->object_edit) {
struct Gwn_Batch *geom = DRW_cache_lattice_wire_get(ob, false);
if (theme_id == TH_UNDEFINED) {
theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
}
DRWShadingGroup *shgroup = shgroup_theme_id_to_wire_or(stl, theme_id, stl->g_data->wire);
- DRW_shgroup_call_add(shgroup, geom, ob->obmat);
+ DRW_shgroup_call_object_add(shgroup, geom, ob);
}
break;
}
case OB_CURVE:
{
- Object *obedit = scene->obedit;
- if (ob != obedit) {
+ if (ob != draw_ctx->object_edit) {
struct Gwn_Batch *geom = DRW_cache_curve_edge_wire_get(ob);
if (theme_id == TH_UNDEFINED) {
theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
}
DRWShadingGroup *shgroup = shgroup_theme_id_to_wire_or(stl, theme_id, stl->g_data->wire);
- DRW_shgroup_call_add(shgroup, geom, ob->obmat);
+ DRW_shgroup_call_object_add(shgroup, geom, ob);
}
break;
}
case OB_MBALL:
{
- Object *obedit = scene->obedit;
- if (ob != obedit) {
- DRW_shgroup_mball_helpers(stl, ob, view_layer);
+ if (ob != draw_ctx->object_edit) {
+ DRW_shgroup_mball_handles(stl, ob, view_layer);
}
break;
}
case OB_GROOM:
{
- Object *obedit = scene->obedit;
- if (ob != obedit) {
+ if (ob != draw_ctx->object_edit) {
Groom *groom = ob->data;
struct Gwn_Batch *geom = DRW_cache_groom_wire_get(ob);
if (theme_id == TH_UNDEFINED) {
@@ -1956,7 +2056,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
{
FurModifierData *fmd = (FurModifierData*)md;
- if (!modifier_isEnabled(scene, md, eModifierMode_Realtime))
+ if (!modifier_isEnabled(draw_ctx->scene, md, eModifierMode_Realtime))
{
continue;
}
@@ -2008,38 +2108,27 @@ static void OBJECT_draw_scene(void *vedata)
if (DRW_state_is_fbo()) {
DRW_stats_group_start("Outlines");
- /* attach temp textures */
- DRW_framebuffer_texture_attach(fbl->outlines, e_data.outlines_depth_tx, 0, 0);
- DRW_framebuffer_texture_attach(fbl->outlines, e_data.outlines_color_tx, 0, 0);
- DRW_framebuffer_texture_attach(fbl->blur, e_data.outlines_blur_tx, 0, 0);
/* Render filled polygon on a separate framebuffer */
- DRW_framebuffer_bind(fbl->outlines);
- DRW_framebuffer_clear(true, true, false, clearcol, 1.0f);
+ GPU_framebuffer_bind(fbl->outlines_fb);
+ GPU_framebuffer_clear_color_depth(fbl->outlines_fb, clearcol, 1.0f);
DRW_draw_pass(psl->outlines);
DRW_draw_pass(psl->lightprobes);
- /* detach textures */
- DRW_framebuffer_texture_detach(e_data.outlines_depth_tx);
-
/* Search outline pixels */
- DRW_framebuffer_bind(fbl->blur);
+ GPU_framebuffer_bind(fbl->blur_fb);
DRW_draw_pass(psl->outlines_search);
/* Expand outline to form a 3px wide line */
- DRW_framebuffer_bind(fbl->outlines);
+ GPU_framebuffer_bind(fbl->expand_fb);
DRW_draw_pass(psl->outlines_expand);
/* Bleed color so the AA can do it's stuff */
- DRW_framebuffer_bind(fbl->blur);
+ GPU_framebuffer_bind(fbl->blur_fb);
DRW_draw_pass(psl->outlines_bleed);
- /* detach temp textures */
- DRW_framebuffer_texture_detach(e_data.outlines_color_tx);
- DRW_framebuffer_texture_detach(e_data.outlines_blur_tx);
-
/* restore main framebuffer */
- DRW_framebuffer_bind(dfbl->default_fb);
+ GPU_framebuffer_bind(dfbl->default_fb);
DRW_stats_group_end();
}
else if (DRW_state_is_select()) {
@@ -2064,9 +2153,9 @@ static void OBJECT_draw_scene(void *vedata)
if (DRW_state_is_fbo()) {
if (e_data.draw_grid) {
- DRW_framebuffer_texture_detach(dtxl->depth);
+ GPU_framebuffer_bind(dfbl->color_only_fb);
DRW_draw_pass(psl->grid);
- DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
+ GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
}
/* Combine with scene buffer last */
@@ -2102,4 +2191,5 @@ DrawEngineType draw_engine_object_type = {
NULL,
&OBJECT_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c
index b49da0cba2f..2a5eabd08fa 100644
--- a/source/blender/draw/modes/paint_texture_mode.c
+++ b/source/blender/draw/modes/paint_texture_mode.c
@@ -414,4 +414,5 @@ DrawEngineType draw_engine_paint_texture_type = {
NULL, /* draw_background but not needed by mode engines */
&PAINT_TEXTURE_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/paint_vertex_mode.c b/source/blender/draw/modes/paint_vertex_mode.c
index e430fca5742..835fefdee26 100644
--- a/source/blender/draw/modes/paint_vertex_mode.c
+++ b/source/blender/draw/modes/paint_vertex_mode.c
@@ -213,4 +213,5 @@ DrawEngineType draw_engine_paint_vertex_type = {
NULL,
&PAINT_VERTEX_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/paint_weight_mode.c b/source/blender/draw/modes/paint_weight_mode.c
index e139b4af97f..3cc2ad63ed4 100644
--- a/source/blender/draw/modes/paint_weight_mode.c
+++ b/source/blender/draw/modes/paint_weight_mode.c
@@ -251,4 +251,5 @@ DrawEngineType draw_engine_paint_weight_type = {
NULL,
&PAINT_WEIGHT_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/particle_mode.c b/source/blender/draw/modes/particle_mode.c
index 6a3e53a72c2..f92505a8778 100644
--- a/source/blender/draw/modes/particle_mode.c
+++ b/source/blender/draw/modes/particle_mode.c
@@ -200,7 +200,7 @@ static void PARTICLE_draw_scene(void *vedata)
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- UNUSED_VARS(fbl, dfbl, dtxl);
+ UNUSED_VARS(fbl, dfbl, dtxl, psl);
/* Show / hide entire passes, swap framebuffers ... whatever you fancy */
/*
@@ -212,7 +212,7 @@ static void PARTICLE_draw_scene(void *vedata)
*/
/* ... or just render passes on default framebuffer. */
- DRW_draw_pass(psl->pass);
+ //DRW_draw_pass(psl->pass);
/* If you changed framebuffer, double check you rebind
* the default one with its textures attached before finishing */
@@ -261,4 +261,5 @@ DrawEngineType draw_engine_particle_type = {
NULL, /* draw_background but not needed by mode engines */
&PARTICLE_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/pose_mode.c b/source/blender/draw/modes/pose_mode.c
index 1c2acd56085..749c3e71368 100644
--- a/source/blender/draw/modes/pose_mode.c
+++ b/source/blender/draw/modes/pose_mode.c
@@ -136,14 +136,16 @@ static void POSE_cache_populate(void *vedata, Object *ob)
*/
bool DRW_pose_mode_armature(Object *ob, Object *active_ob)
{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
/* Pode armature is handled by pose mode engine. */
- if ((ob == active_ob) && ((ob->mode & OB_MODE_POSE) != 0)) {
+ if ((ob == active_ob) && ((draw_ctx->object_mode & OB_MODE_POSE) != 0)) {
return true;
}
/* Armature parent is also handled by pose mode engine. */
- if ((active_ob != NULL) && ((active_ob->mode & OB_MODE_WEIGHT_PAINT) != 0)) {
- if (active_ob->parent == ob) {
+ if ((active_ob != NULL) && ((draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) != 0)) {
+ if (ob == draw_ctx->object_pose) {
return true;
}
}
@@ -195,4 +197,5 @@ DrawEngineType draw_engine_pose_type = {
NULL,
&POSE_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/sculpt_mode.c b/source/blender/draw/modes/sculpt_mode.c
index d9f1f5ebe91..65f4653591f 100644
--- a/source/blender/draw/modes/sculpt_mode.c
+++ b/source/blender/draw/modes/sculpt_mode.c
@@ -193,12 +193,8 @@ static void SCULPT_cache_populate(void *vedata, Object *ob)
if (ob->type == OB_MESH) {
const DRWContextState *draw_ctx = DRW_context_state_get();
- EvaluationContext eval_ctx;
-
- CTX_data_eval_ctx(draw_ctx->evil_C, &eval_ctx);
if (ob->sculpt && (ob == draw_ctx->obact)) {
-
/* XXX, needed for dyntopo-undo (which clears).
* probably depsgraph should handlle? in 2.7x getting derived-mesh does this (mesh_build_data) */
if (ob->sculpt->pbvh == NULL) {
@@ -206,7 +202,7 @@ static void SCULPT_cache_populate(void *vedata, Object *ob)
* but this avoids waiting on first stroke) */
Scene *scene = draw_ctx->scene;
- BKE_sculpt_update_mesh_elements(&eval_ctx, scene, scene->toolsettings->sculpt, ob, false, false);
+ BKE_sculpt_update_mesh_elements(&draw_ctx->eval_ctx, scene, scene->toolsettings->sculpt, ob, false, false);
}
PBVH *pbvh = ob->sculpt->pbvh;
@@ -302,4 +298,5 @@ DrawEngineType draw_engine_sculpt_type = {
NULL, /* draw_background but not needed by mode engines */
&SCULPT_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl b/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl
index fc5cc1cdcc3..fc5cc1cdcc3 100644
--- a/source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl
+++ b/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl
diff --git a/source/blender/draw/modes/shaders/common_view_lib.glsl b/source/blender/draw/modes/shaders/common_view_lib.glsl
new file mode 100644
index 00000000000..d261d263a6f
--- /dev/null
+++ b/source/blender/draw/modes/shaders/common_view_lib.glsl
@@ -0,0 +1,14 @@
+/* keep in sync with DRWManager.view_data */
+layout(std140) uniform viewBlock {
+ /* Same order as DRWViewportMatrixType */
+ mat4 ViewProjectionMatrix;
+ mat4 ViewProjectionMatrixInverse;
+ mat4 ViewMatrix;
+ mat4 ViewMatrixInverse;
+ mat4 ProjectionMatrix;
+ mat4 ProjectionMatrixInverse;
+
+ vec4 CameraTexCoFactors;
+
+ vec4 clipPlanes[2];
+};
diff --git a/source/blender/draw/modes/shaders/object_particle_prim_frag.glsl b/source/blender/draw/modes/shaders/object_particle_prim_frag.glsl
deleted file mode 100644
index aa455a85cf0..00000000000
--- a/source/blender/draw/modes/shaders/object_particle_prim_frag.glsl
+++ /dev/null
@@ -1,9 +0,0 @@
-
-flat in vec4 finalColor;
-
-out vec4 fragColor;
-
-void main()
-{
- fragColor = finalColor;
-}
diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt
index 00b514d1a15..e626636e1ab 100644
--- a/source/blender/editors/CMakeLists.txt
+++ b/source/blender/editors/CMakeLists.txt
@@ -30,6 +30,7 @@ if(WITH_BLENDER)
add_subdirectory(groom)
add_subdirectory(interface)
add_subdirectory(io)
+ add_subdirectory(lattice)
add_subdirectory(manipulator_library)
add_subdirectory(mask)
add_subdirectory(mesh)
@@ -60,6 +61,7 @@ if(WITH_BLENDER)
add_subdirectory(space_userpref)
add_subdirectory(space_view3d)
add_subdirectory(transform)
+ add_subdirectory(undo)
add_subdirectory(util)
add_subdirectory(uvedit)
add_subdirectory(screen)
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 9fb30dc8066..87fe002e536 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -3827,7 +3827,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
selected = 0;
/* set blending again, as may not be set in previous step */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
/* step 1) draw backdrop ........................................... */
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 0db465e583b..4af8089ffea 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -225,6 +225,33 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
ANIM_animdata_freelist(&anim_data);
}
+static void select_pchan_for_action_group(bAnimContext *ac, bActionGroup *agrp, bAnimListElem *ale)
+{
+ /* Armatures-Specific Feature:
+ * See mouse_anim_channels() -> ANIMTYPE_GROUP case for more details (T38737)
+ */
+ if ((ac->ads->filterflag & ADS_FILTER_ONLYSEL) == 0) {
+ if ((ale->id) && (GS(ale->id->name) == ID_OB)) {
+ Object *ob = (Object *)ale->id;
+ if (ob->type == OB_ARMATURE) {
+ /* Assume for now that any group with corresponding name is what we want
+ * (i.e. for an armature whose location is animated, things would break
+ * if the user were to add a bone named "Location").
+ *
+ * TODO: check the first F-Curve or so to be sure...
+ */
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name);
+ if (agrp->flag & AGRP_SELECTED) {
+ ED_pose_bone_select(ob, pchan, true);
+ }
+ else {
+ ED_pose_bone_select(ob, pchan, false);
+ }
+ }
+ }
+ }
+}
+
/* Deselect all animation channels
* - data: pointer to datatype, as contained in bAnimContext
* - datatype: the type of data that 'data' represents (eAnimCont_Types)
@@ -345,8 +372,8 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
case ANIMTYPE_GROUP:
{
bActionGroup *agrp = (bActionGroup *)ale->data;
-
ACHANNEL_SET_FLAG(agrp, sel, AGRP_SELECTED);
+ select_pchan_for_action_group(ac, agrp, ale);
agrp->flag &= ~AGRP_ACTIVE;
break;
}
@@ -2398,33 +2425,7 @@ static void borderselect_anim_channels(bAnimContext *ac, rcti *rect, short selec
case ANIMTYPE_GROUP:
{
bActionGroup *agrp = (bActionGroup *)ale->data;
-
- /* Armatures-Specific Feature:
- * See mouse_anim_channels() -> ANIMTYPE_GROUP case for more details (T38737)
- */
- if ((ac->ads->filterflag & ADS_FILTER_ONLYSEL) == 0) {
- if ((ale->id) && (GS(ale->id->name) == ID_OB)) {
- Object *ob = (Object *)ale->id;
-
- if (ob->type == OB_ARMATURE) {
- /* Assume for now that any group with corresponding name is what we want
- * (i.e. for an armature whose location is animated, things would break
- * if the user were to add a bone named "Location").
- *
- * TODO: check the first F-Curve or so to be sure...
- */
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name);
-
- if (agrp->flag & AGRP_SELECTED) {
- ED_pose_bone_select(ob, pchan, true);
- }
- else {
- ED_pose_bone_select(ob, pchan, false);
- }
- }
- }
- }
-
+ select_pchan_for_action_group(ac, agrp, ale);
/* always clear active flag after doing this */
agrp->flag &= ~AGRP_ACTIVE;
break;
@@ -2682,8 +2683,10 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
}
case ANIMTYPE_OBJECT:
{
+#if 0
bDopeSheet *ads = (bDopeSheet *)ac->data;
Scene *sce = (Scene *)ads->source;
+#endif
ViewLayer *view_layer = ac->view_layer;
Base *base = (Base *)ale->data;
Object *ob = base->object;
@@ -2722,8 +2725,8 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
adt->flag |= ADT_UI_ACTIVE;
/* ensure we exit editmode on whatever object was active before to avoid getting stuck there - T48747 */
- if (ob != sce->obedit)
- ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
+ if (ob != CTX_data_edit_object(C))
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR | EM_DO_UNDO);
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
}
@@ -3087,7 +3090,7 @@ static bool select_anim_channel_keys(bAnimContext *ac, int channel_index, bool e
for (ale = anim_data.first; ale; ale = ale->next) {
FCurve *fcu_inner = (FCurve *)ale->key_data;
- if (fcu_inner) {
+ if (fcu_inner != NULL && fcu_inner->bezt != NULL) {
for (i = 0, bezt = fcu_inner->bezt; i < fcu_inner->totvert; i++, bezt++) {
bezt->f2 = bezt->f1 = bezt->f3 = 0;
}
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 08851cebf51..9a07eaf896c 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -160,7 +160,7 @@ void ANIM_draw_previewrange(const bContext *C, View2D *v2d, int end_frame_width)
/* only draw this if preview range is set */
if (PRVRANGEON) {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
Gwn_VertFormat *format = immVertexFormat();
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index bc901d7e13f..85bcfb603cd 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -116,7 +116,7 @@ static void animedit_get_yscale_factor(bAnimContext *ac)
/* grab scale factor directly from action editor setting
* NOTE: This theme setting doesn't have an ID, as it cannot be accessed normally
- * since it is a float, and the theem settings methods can only handle chars.
+ * since it is a float, and the theme settings methods can only handle chars.
*/
ac->yscale_fac = btheme->tact.keyframe_scale_fac;
@@ -880,6 +880,7 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
break;
}
case ANIMTYPE_FCURVE:
+ case ANIMTYPE_NLACURVE: /* practically the same as ANIMTYPE_FCURVE. Differences are applied post-creation */
{
FCurve *fcu = (FCurve *)data;
@@ -1089,13 +1090,14 @@ static bool name_matches_dopesheet_filter(bDopeSheet *ads, char *name)
/* (Display-)Name-based F-Curve filtering
* NOTE: when this function returns true, the F-Curve is to be skipped
*/
-static bool skip_fcurve_with_name(bDopeSheet *ads, FCurve *fcu, ID *owner_id)
+static bool skip_fcurve_with_name(bDopeSheet *ads, FCurve *fcu, eAnim_ChannelType channel_type, void *owner, ID *owner_id)
{
bAnimListElem ale_dummy = {NULL};
const bAnimChannelType *acf;
- /* create a dummy wrapper for the F-Curve */
- ale_dummy.type = ANIMTYPE_FCURVE;
+ /* create a dummy wrapper for the F-Curve, so we can get typeinfo for it */
+ ale_dummy.type = channel_type;
+ ale_dummy.owner = owner;
ale_dummy.id = owner_id;
ale_dummy.data = fcu;
@@ -1158,8 +1160,9 @@ static bool fcurve_has_errors(FCurve *fcu)
}
/* find the next F-Curve that is usable for inclusion */
-static FCurve *animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, bActionGroup *grp, int filter_mode, ID *owner_id)
+static FCurve *animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, eAnim_ChannelType channel_type, int filter_mode, void *owner, ID *owner_id)
{
+ bActionGroup *grp = (channel_type == ANIMTYPE_FCURVE) ? owner : NULL;
FCurve *fcu = NULL;
/* loop over F-Curves - assume that the caller of this has already checked that these should be included
@@ -1193,7 +1196,7 @@ static FCurve *animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, bActionGro
if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) {
/* name based filtering... */
if ( ((ads) && (ads->filterflag & ADS_FILTER_BY_FCU_NAME)) && (owner_id) ) {
- if (skip_fcurve_with_name(ads, fcu, owner_id))
+ if (skip_fcurve_with_name(ads, fcu, channel_type, owner, owner_id))
continue;
}
@@ -1216,7 +1219,10 @@ static FCurve *animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, bActionGro
return NULL;
}
-static size_t animfilter_fcurves(ListBase *anim_data, bDopeSheet *ads, FCurve *first, bActionGroup *grp, int filter_mode, ID *owner_id)
+static size_t animfilter_fcurves(ListBase *anim_data, bDopeSheet *ads,
+ FCurve *first, eAnim_ChannelType fcurve_type,
+ int filter_mode,
+ void *owner, ID *owner_id)
{
FCurve *fcu;
size_t items = 0;
@@ -1230,8 +1236,18 @@ static size_t animfilter_fcurves(ListBase *anim_data, bDopeSheet *ads, FCurve *f
* 4) the fcu pointer is set to the F-Curve after the one we just added, so that we can keep going through
* the rest of the F-Curve list without an eternal loop. Back to step 2 :)
*/
- for (fcu = first; ( (fcu = animfilter_fcurve_next(ads, fcu, grp, filter_mode, owner_id)) ); fcu = fcu->next) {
- ANIMCHANNEL_NEW_CHANNEL(fcu, ANIMTYPE_FCURVE, owner_id);
+ for (fcu = first; ( (fcu = animfilter_fcurve_next(ads, fcu, fcurve_type, filter_mode, owner, owner_id)) ); fcu = fcu->next) {
+ if (UNLIKELY(fcurve_type == ANIMTYPE_NLACURVE)) {
+ /* NLA Control Curve - Basically the same as normal F-Curves, except we need to set some stuff differently */
+ ANIMCHANNEL_NEW_CHANNEL_FULL(fcu, ANIMTYPE_NLACURVE, owner_id, {
+ ale->owner = owner; /* strip */
+ ale->adt = NULL; /* to prevent time mapping from causing problems */
+ });
+ }
+ else {
+ /* Normal FCurve */
+ ANIMCHANNEL_NEW_CHANNEL(fcu, ANIMTYPE_FCURVE, owner_id);
+ }
}
/* return the number of items added to the list */
@@ -1282,10 +1298,10 @@ static size_t animfilter_act_group(bAnimContext *ac, ListBase *anim_data, bDopeS
/* group must be editable for its children to be editable (if we care about this) */
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
/* get first F-Curve which can be used here */
- FCurve *first_fcu = animfilter_fcurve_next(ads, agrp->channels.first, agrp, filter_mode, owner_id);
+ FCurve *first_fcu = animfilter_fcurve_next(ads, agrp->channels.first, ANIMTYPE_FCURVE, filter_mode, agrp, owner_id);
/* filter list, starting from this F-Curve */
- tmp_items += animfilter_fcurves(&tmp_data, ads, first_fcu, agrp, filter_mode, owner_id);
+ tmp_items += animfilter_fcurves(&tmp_data, ads, first_fcu, ANIMTYPE_FCURVE, filter_mode, agrp, owner_id);
}
}
}
@@ -1341,7 +1357,7 @@ static size_t animfilter_action(bAnimContext *ac, ListBase *anim_data, bDopeShee
/* un-grouped F-Curves (only if we're not only considering those channels in the active group) */
if (!(filter_mode & ANIMFILTER_ACTGROUPED)) {
FCurve *firstfcu = (lastchan) ? (lastchan->next) : (act->curves.first);
- items += animfilter_fcurves(anim_data, ads, firstfcu, NULL, filter_mode, owner_id);
+ items += animfilter_fcurves(anim_data, ads, firstfcu, ANIMTYPE_FCURVE, filter_mode, NULL, owner_id);
}
/* return the number of items added to the list */
@@ -1463,36 +1479,8 @@ static size_t animfilter_nla_controls(ListBase *anim_data, bDopeSheet *ads, Anim
/* for now, we only go one level deep - so controls on grouped FCurves are not handled */
for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
for (strip = nlt->strips.first; strip; strip = strip->next) {
- ListBase strip_curves = {NULL, NULL};
- size_t strip_items = 0;
-
- /* create the raw items */
- strip_items += animfilter_fcurves(&strip_curves, ads, strip->fcurves.first, NULL, filter_mode, owner_id);
-
- /* change their types and add extra data
- * - There is no point making a separate copy of animfilter_fcurves for this now/yet,
- * unless we later get per-element control curves for other stuff too
- */
- if (strip_items) {
- bAnimListElem *ale, *ale_n = NULL;
-
- for (ale = strip_curves.first; ale; ale = ale_n) {
- ale_n = ale->next;
-
- /* change the type to being a FCurve for editing NLA strip controls */
- BLI_assert(ale->type == ANIMTYPE_FCURVE);
-
- ale->type = ANIMTYPE_NLACURVE;
- ale->owner = strip;
-
- ale->adt = NULL; /* XXX: This way, there are no problems with time mapping errors */
- }
- }
-
- /* add strip curves to the set of channels inside the group being collected */
- BLI_movelisttolist(&tmp_data, &strip_curves);
- BLI_assert(BLI_listbase_is_empty(&strip_curves));
- tmp_items += strip_items;
+ /* pass strip as the "owner", so that the name lookups (used while filtering) will resolve */
+ tmp_items += animfilter_fcurves(&tmp_data, ads, strip->fcurves.first, ANIMTYPE_NLACURVE, filter_mode, strip, owner_id);
}
}
}
@@ -1543,7 +1531,7 @@ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDope
items += animfilter_nla(ac, anim_data, ads, adt, filter_mode, id);
},
{ /* Drivers */
- items += animfilter_fcurves(anim_data, ads, adt->drivers.first, NULL, filter_mode, id);
+ items += animfilter_fcurves(anim_data, ads, adt->drivers.first, ANIMTYPE_FCURVE, filter_mode, NULL, id);
},
{ /* NLA Control Keyframes */
items += animfilter_nla_controls(anim_data, ads, adt, filter_mode, id);
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 107a46999f0..e43735c51fb 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -345,7 +345,7 @@ static void draw_marker(
int icon_id;
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
/* vertical line - dotted */
#ifdef DURIAN_CAMERA_SWITCH
@@ -462,7 +462,7 @@ void ED_markers_draw(const bContext *C, int flag)
immUniformColor4ubv(shade);
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
immRectf(pos, v2d->cur.xmin, 0, v2d->cur.xmax, UI_MARKER_MARGIN_Y);
@@ -1113,14 +1113,15 @@ static void select_timeline_marker_frame(ListBase *markers, int frame, bool exte
}
}
- BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN (markers, marker, marker_first) {
+ LISTBASE_CIRCULAR_FORWARD_BEGIN(markers, marker, marker_first)
+ {
/* this way a not-extend select will always give 1 selected marker */
if (marker->frame == frame) {
marker->flag ^= SELECT;
break;
}
}
- BLI_LISTBASE_CIRCULAR_FORWARD_END (markers, marker, marker_first);
+ LISTBASE_CIRCULAR_FORWARD_END(markers, marker, marker_first);
}
static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool camera)
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index 8d77460e197..8106be79521 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -62,7 +62,7 @@
#include "UI_resources.h"
#include "ED_anim_api.h"
-#include "ED_util.h"
+#include "ED_undo.h"
/* ********************************************** */
/* UI STUFF */
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index 9d25fc9e1a3..0ef6aa4bd4a 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -36,7 +36,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BLI_lasso.h"
+#include "BLI_lasso_2d.h"
#include "BLI_math.h"
#include "DNA_anim_types.h"
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 24f6a2dab2c..126e4b5f736 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -1358,7 +1358,7 @@ static int insert_key_exec(bContext *C, wmOperator *op)
* updated since the last switching to the edit mode will be keyframed correctly
*/
if (obedit && ANIM_keyingset_find_id(ks, (ID *)obedit->data)) {
- ED_object_toggle_modes(C, OB_MODE_EDIT);
+ ED_object_mode_toggle(C, OB_MODE_EDIT);
ob_edit_mode = true;
}
@@ -1369,7 +1369,7 @@ static int insert_key_exec(bContext *C, wmOperator *op)
/* restore the edit mode if necessary */
if (ob_edit_mode) {
- ED_object_toggle_modes(C, OB_MODE_EDIT);
+ ED_object_mode_toggle(C, OB_MODE_EDIT);
}
/* report failure or do updates? */
diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt
index 5348298f57e..4301fe6582f 100644
--- a/source/blender/editors/armature/CMakeLists.txt
+++ b/source/blender/editors/armature/CMakeLists.txt
@@ -49,6 +49,7 @@ set(SRC
editarmature_generate.c
editarmature_retarget.c
editarmature_sketch.c
+ editarmature_undo.c
meshlaplacian.c
pose_edit.c
pose_lib.c
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index 368d54fc3ad..bd3ddfe93c6 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -472,7 +472,7 @@ EditBone *duplicateEditBone(EditBone *curBone, const char *name, ListBase *editb
return duplicateEditBoneObjects(curBone, name, editbones, ob, ob);
}
-static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op))
+static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
{
bArmature *arm;
EditBone *ebone_iter;
@@ -484,7 +484,9 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op))
/* cancel if nothing selected */
if (CTX_DATA_COUNT(C, selected_bones) == 0)
return OPERATOR_CANCELLED;
-
+
+ const bool do_flip_names = RNA_boolean_get(op->ptr, "do_flip_names");
+
ED_armature_sync_selection(arm->edbo); // XXX why is this needed?
preEditBoneDuplicate(arm->edbo);
@@ -512,8 +514,20 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op))
(ebone_iter->flag & BONE_SELECTED))
{
EditBone *ebone;
+ char new_bone_name_buff[MAXBONENAME];
+ char *new_bone_name = ebone_iter->name;
+
+ if (do_flip_names) {
+ BLI_string_flip_side_name(new_bone_name_buff, ebone_iter->name, false, sizeof(new_bone_name_buff));
- ebone = duplicateEditBone(ebone_iter, ebone_iter->name, arm->edbo, obedit);
+ /* Only use flipped name if not yet in use. Otherwise we'd get again inconsistent namings
+ * (different numbers), better keep default behavior in this case. */
+ if (ED_armature_bone_find_name(arm->edbo, new_bone_name_buff) == NULL) {
+ new_bone_name = new_bone_name_buff;
+ }
+ }
+
+ ebone = duplicateEditBone(ebone_iter, new_bone_name, arm->edbo, obedit);
if (!ebone_first_dupe) {
ebone_first_dupe = ebone;
@@ -590,6 +604,10 @@ void ARMATURE_OT_duplicate(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(
+ ot->srna, "do_flip_names", false,
+ "Flip Names", "Try to flip names of the bones, if possible, instead of adding a number extension");
}
/**
@@ -1011,7 +1029,7 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
ED_armature_deselect_all(obedit);
- /* Create a bone */
+ /* Create a bone */
bone = ED_armature_edit_bone_add(obedit->data, name);
copy_v3_v3(bone->head, curs);
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index a2fbfe645f7..bb3c4164fc1 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -50,6 +50,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_report.h"
+#include "BKE_object.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -138,17 +139,16 @@ void ED_armature_transform(struct bArmature *arm, float mat[4][4], const bool do
/* exported for use in editors/object/ */
/* 0 == do center, 1 == center new, 2 == center cursor */
-void ED_armature_origin_set(Scene *scene, Object *ob, float cursor[3], int centermode, int around)
+void ED_armature_origin_set(Object *ob, float cursor[3], int centermode, int around)
{
- Object *obedit = scene->obedit; // XXX get from context
+ const bool is_editmode = BKE_object_is_in_editmode(ob);
EditBone *ebone;
bArmature *arm = ob->data;
float cent[3];
/* Put the armature into editmode */
- if (ob != obedit) {
+ if (is_editmode == false) {
ED_armature_to_edit(arm);
- obedit = NULL; /* we cant use this so behave as if there is no obedit */
}
/* Find the centerpoint */
@@ -188,13 +188,13 @@ void ED_armature_origin_set(Scene *scene, Object *ob, float cursor[3], int cente
}
/* Turn the list into an armature */
- if (obedit == NULL) {
+ if (is_editmode == false) {
ED_armature_from_edit(arm);
ED_armature_edit_free(arm);
}
/* Adjust object location for new centerpoint */
- if (centermode && obedit == NULL) {
+ if (centermode && (is_editmode == false)) {
mul_mat3_m4_v3(ob->obmat, cent); /* omit translation part */
add_v3_v3(ob->loc, cent);
}
@@ -1458,8 +1458,9 @@ static int armature_dissolve_selected_exec(bContext *C, wmOperator *UNUSED(op))
if (ebone->flag & BONE_DONE) {
copy_v3_v3(ebone->parent->tail, ebone->tail);
ebone->parent->rad_tail = ebone->rad_tail;
+ SET_FLAG_FROM_TEST(ebone->parent->flag, ebone->flag & BONE_TIPSEL, BONE_TIPSEL);
- ED_armature_edit_bone_remove(arm, ebone);
+ ED_armature_edit_bone_remove_ex(arm, ebone, false);
changed = true;
}
}
@@ -1468,10 +1469,9 @@ static int armature_dissolve_selected_exec(bContext *C, wmOperator *UNUSED(op))
for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
if (ebone->parent &&
ebone->parent->temp.ebone &&
- (ebone->flag & BONE_CONNECTED) == 0)
+ (ebone->flag & BONE_CONNECTED))
{
- ebone->flag |= BONE_CONNECTED;
- ebone->rad_head = ebone->parent->rad_head;
+ ebone->rad_head = ebone->parent->rad_tail;
}
}
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index 192bb8eea61..0ba720a17d0 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -250,7 +250,7 @@ void armature_tag_unselect(struct bArmature *arm);
void *get_nearest_bone(struct bContext *C, const int xy[2], bool findunsel);
void *get_bone_from_selectbuffer(
- struct Scene *scene, struct Base *base, const unsigned int *buffer, short hits,
+ struct Base *base, struct Object *obedit, const unsigned int *buffer, short hits,
bool findunsel, bool do_nearest);
int bone_looper(struct Object *ob, struct Bone *bone, void *data,
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index 0d114206c6b..52e9e424a85 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -314,8 +314,9 @@ typedef struct BoneFlipNameData {
*
* \param arm: Armature the bones belong to
* \param bones_names: List of BoneConflict elems.
+ * \param do_strip_numbers: if set, try to get rid of dot-numbers at end of bone names.
*/
-void ED_armature_bones_flip_names(bArmature *arm, ListBase *bones_names)
+void ED_armature_bones_flip_names(bArmature *arm, ListBase *bones_names, const bool do_strip_numbers)
{
ListBase bones_names_conflicts = {NULL};
BoneFlipNameData *bfn;
@@ -327,9 +328,9 @@ void ED_armature_bones_flip_names(bArmature *arm, ListBase *bones_names)
char name_flip[MAXBONENAME];
char *name = link->data;
- /* Do not strip numbers, otherwise we'll end up with completely mismatched names in cases like
+ /* WARNING: if do_strip_numbers is set, expect completely mismatched names in cases like
* Bone.R, Bone.R.001, Bone.R.002, etc. */
- BLI_string_flip_side_name(name_flip, name, false, sizeof(name_flip));
+ BLI_string_flip_side_name(name_flip, name, do_strip_numbers, sizeof(name_flip));
ED_armature_bone_rename(arm, name, name_flip);
@@ -352,7 +353,7 @@ void ED_armature_bones_flip_names(bArmature *arm, ListBase *bones_names)
/* ************************************************** */
/* Bone Renaming - EditMode */
-static int armature_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
+static int armature_flip_names_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_edit_object(C);
bArmature *arm;
@@ -361,6 +362,8 @@ static int armature_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
+ const bool do_strip_numbers = RNA_boolean_get(op->ptr, "do_strip_numbers");
+
arm = ob->data;
ListBase bones_names = {NULL};
@@ -371,7 +374,7 @@ static int armature_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
}
CTX_DATA_END;
- ED_armature_bones_flip_names(arm, &bones_names);
+ ED_armature_bones_flip_names(arm, &bones_names, do_strip_numbers);
BLI_freelistN(&bones_names);
@@ -401,6 +404,10 @@ void ARMATURE_OT_flip_names(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "do_strip_numbers", false, "Strip Numbers",
+ "Try to remove right-most dot-number from flipped names "
+ "(WARNING: may result in incoherent naming in some cases)");
}
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index ccaa9ecb8de..de2611f7092 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -130,46 +130,36 @@ typedef struct tJoinArmature_AdtFixData {
/* FIXME: For now, we only care about drivers here. When editing rigs, it's very rare to have animation
* on the rigs being edited already, so it should be safe to skip these.
*/
-static void joined_armature_fix_animdata_cb(ID *id, AnimData *adt, void *user_data)
+static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data)
{
tJoinArmature_AdtFixData *afd = (tJoinArmature_AdtFixData *)user_data;
ID *src_id = &afd->srcArm->id;
ID *dst_id = &afd->tarArm->id;
GHashIterator gh_iter;
- FCurve *fcu;
/* Fix paths - If this is the target object, it will have some "dirty" paths */
- if (id == src_id) {
- /* Fix drivers */
- for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
- /* skip driver if it doesn't affect the bones */
- if (strstr(fcu->rna_path, "pose.bones[") == NULL) {
- continue;
- }
+ if ((id == src_id) && strstr(fcu->rna_path, "pose.bones[")) {
+ GHASH_ITER(gh_iter, afd->names_map) {
+ const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
+ const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
- // FIXME: this is too crude... it just does everything!
- GHASH_ITER(gh_iter, afd->names_map) {
- const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
- const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
+ /* only remap if changed; this still means there will be some waste if there aren't many drivers/keys */
+ if (!STREQ(old_name, new_name) && strstr(fcu->rna_path, old_name)) {
+ fcu->rna_path = BKE_animsys_fix_rna_path_rename(id, fcu->rna_path, "pose.bones",
+ old_name, new_name, 0, 0, false);
- /* only remap if changed; this still means there will be some waste if there aren't many drivers/keys */
- if (!STREQ(old_name, new_name) && strstr(fcu->rna_path, old_name)) {
- fcu->rna_path = BKE_animsys_fix_rna_path_rename(id, fcu->rna_path, "pose.bones",
- old_name, new_name, 0, 0, false);
-
- /* we don't want to apply a second remapping on this driver now,
- * so stop trying names, but keep fixing drivers
- */
- break;
- }
+ /* we don't want to apply a second remapping on this driver now,
+ * so stop trying names, but keep fixing drivers
+ */
+ break;
}
}
}
/* Driver targets */
- for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
+ if (fcu->driver) {
ChannelDriver *driver = fcu->driver;
DriverVar *dvar;
@@ -373,7 +363,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
}
/* Fix all the drivers (and animation data) */
- BKE_animdata_main_cb(bmain, joined_armature_fix_animdata_cb, &afd);
+ BKE_fcurves_main_cb(bmain, joined_armature_fix_animdata_cb, &afd);
BLI_ghash_free(afd.names_map, MEM_freeN, NULL);
/* Only copy over animdata now, after all the remapping has been done,
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index b87942fed84..397691a409b 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -77,10 +77,9 @@ Bone *get_indexed_bone(Object *ob, int index)
/* See if there are any selected bones in this buffer */
/* only bones from base are checked on */
void *get_bone_from_selectbuffer(
- Scene *scene, Base *base, const unsigned int *buffer, short hits,
+ Base *base, Object *obedit, const unsigned int *buffer, short hits,
bool findunsel, bool do_nearest)
{
- Object *obedit = scene->obedit; // XXX get from context
Bone *bone;
EditBone *ebone;
void *firstunSel = NULL, *firstSel = NULL, *data;
@@ -175,7 +174,7 @@ void *get_nearest_bone(bContext *C, const int xy[2], bool findunsel)
short hits;
CTX_data_eval_ctx(C, &eval_ctx);
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
// rect.xmin = ... mouseco!
rect.xmin = rect.xmax = xy[0];
@@ -183,9 +182,9 @@ void *get_nearest_bone(bContext *C, const int xy[2], bool findunsel)
hits = view3d_opengl_select(&eval_ctx, &vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
- if (hits > 0)
- return get_bone_from_selectbuffer(vc.scene, vc.view_layer->basact, buffer, hits, findunsel, true);
-
+ if (hits > 0) {
+ return get_bone_from_selectbuffer(vc.view_layer->basact, vc.obedit, buffer, hits, findunsel, true);
+ }
return NULL;
}
@@ -492,7 +491,7 @@ bool ED_armature_select_pick(bContext *C, const int mval[2], bool extend, bool d
int selmask;
CTX_data_eval_ctx(C, &eval_ctx);
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
if (BIF_sk_selectStroke(C, mval, extend)) {
return true;
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
index 72b4837c1b8..5c8e08a0d89 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -66,7 +66,7 @@
/* ********************************** Bone Skinning *********************************************** */
-static int bone_skinnable_cb(Object *ob, Bone *bone, void *datap)
+static int bone_skinnable_cb(Object *UNUSED(ob), Bone *bone, void *datap)
{
/* Bones that are deforming
* are regarded to be "skinnable" and are eligible for
@@ -92,9 +92,9 @@ static int bone_skinnable_cb(Object *ob, Bone *bone, void *datap)
*/
Bone ***hbone;
int a, segments;
- struct { Object *armob; void *list; int heat; } *data = datap;
+ struct { Object *armob; void *list; int heat; bool is_weight_paint; } *data = datap;
- if (!(ob->mode & OB_MODE_WEIGHT_PAINT) || !(bone->flag & BONE_HIDDEN_P)) {
+ if (!(data->is_weight_paint) || !(bone->flag & BONE_HIDDEN_P)) {
if (!(bone->flag & BONE_NO_DEFORM)) {
if (data->heat && data->armob->pose && BKE_pose_channel_find_name(data->armob->pose, bone->name))
segments = bone->segments;
@@ -157,18 +157,17 @@ static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
*/
bDeformGroup ***hgroup, *defgroup = NULL;
int a, segments;
- struct { Object *armob; void *list; int heat; } *data = datap;
- int wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
+ struct { Object *armob; void *list; int heat; bool is_weight_paint; } *data = datap;
bArmature *arm = data->armob->data;
- if (!wpmode || !(bone->flag & BONE_HIDDEN_P)) {
+ if (!data->is_weight_paint || !(bone->flag & BONE_HIDDEN_P)) {
if (!(bone->flag & BONE_NO_DEFORM)) {
if (data->heat && data->armob->pose && BKE_pose_channel_find_name(data->armob->pose, bone->name))
segments = bone->segments;
else
segments = 1;
- if (!wpmode || ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))) {
+ if (!data->is_weight_paint || ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))) {
if (!(defgroup = defgroup_find_name(ob, bone->name))) {
defgroup = BKE_object_defgroup_add_name(ob, bone->name);
}
@@ -192,9 +191,10 @@ static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
return 0;
}
-static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], int numbones, Bone **bonelist,
- bDeformGroup **dgrouplist, bDeformGroup **dgroupflip,
- float (*root)[3], float (*tip)[3], const int *selected, float scale)
+static void envelope_bone_weighting(
+ Object *ob, Mesh *mesh, float (*verts)[3], int numbones, Bone **bonelist,
+ bDeformGroup **dgrouplist, bDeformGroup **dgroupflip,
+ float (*root)[3], float (*tip)[3], const int *selected, float scale)
{
/* Create vertex group weights from envelopes */
@@ -276,12 +276,13 @@ static void add_verts_to_dgroups(
float (*root)[3], (*tip)[3], (*verts)[3];
int *selected;
int numbones, vertsfilled = 0, i, j, segments = 0;
- int wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
- struct { Object *armob; void *list; int heat; } looper_data;
+ const bool wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
+ struct { Object *armob; void *list; int heat; bool is_weight_paint; } looper_data;
looper_data.armob = par;
looper_data.heat = heat;
looper_data.list = NULL;
+ looper_data.is_weight_paint = wpmode;
/* count the number of skinnable bones */
numbones = bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
@@ -404,15 +405,17 @@ static void add_verts_to_dgroups(
if (heat) {
const char *error = NULL;
- heat_bone_weighting(ob, mesh, verts, numbones, dgrouplist, dgroupflip,
- root, tip, selected, &error);
+ heat_bone_weighting(
+ ob, mesh, verts, numbones, dgrouplist, dgroupflip,
+ root, tip, selected, &error);
if (error) {
BKE_report(reports, RPT_WARNING, error);
}
}
else {
- envelope_bone_weighting(ob, mesh, verts, numbones, bonelist, dgrouplist,
- dgroupflip, root, tip, selected, mat4_to_scale(par->obmat));
+ envelope_bone_weighting(
+ ob, mesh, verts, numbones, bonelist, dgrouplist,
+ dgroupflip, root, tip, selected, mat4_to_scale(par->obmat));
}
/* only generated in some cases but can call anyway */
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index f27c4fdd96f..aa0aa0e03ff 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -134,7 +134,10 @@ void bone_free(bArmature *arm, EditBone *bone)
BLI_freelinkN(arm->edbo, bone);
}
-void ED_armature_edit_bone_remove(bArmature *arm, EditBone *exBone)
+/**
+ * \param clear_connected: When false caller is responsible for keeping the flag in a valid state.
+ */
+void ED_armature_edit_bone_remove_ex(bArmature *arm, EditBone *exBone, bool clear_connected)
{
EditBone *curBone;
@@ -142,13 +145,20 @@ void ED_armature_edit_bone_remove(bArmature *arm, EditBone *exBone)
for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
if (curBone->parent == exBone) {
curBone->parent = exBone->parent;
- curBone->flag &= ~BONE_CONNECTED;
+ if (clear_connected) {
+ curBone->flag &= ~BONE_CONNECTED;
+ }
}
}
bone_free(arm, exBone);
}
+void ED_armature_edit_bone_remove(bArmature *arm, EditBone *exBone)
+{
+ ED_armature_edit_bone_remove_ex(arm, exBone, true);
+}
+
bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child)
{
for (ebone_child = ebone_child->parent; ebone_child; ebone_child = ebone_child->parent) {
@@ -592,7 +602,7 @@ void ED_armature_from_edit(bArmature *arm)
if (len_sq <= SQUARE(0.000001f)) { /* FLT_EPSILON is too large? */
EditBone *fBone;
- /* Find any bones that refer to this bone */
+ /* Find any bones that refer to this bone */
for (fBone = arm->edbo->first; fBone; fBone = fBone->next) {
if (fBone->parent == eBone)
fBone->parent = eBone->parent;
@@ -711,11 +721,11 @@ void ED_armature_to_edit(bArmature *arm)
}
/* *************************************************************** */
-/* Undo for Armature EditMode*/
+/* Used by Undo for Armature EditMode*/
/* free's bones and their properties */
-static void ED_armature_ebone_listbase_free(ListBase *lb)
+void ED_armature_ebone_listbase_free(ListBase *lb)
{
EditBone *ebone, *ebone_next;
@@ -733,7 +743,7 @@ static void ED_armature_ebone_listbase_free(ListBase *lb)
BLI_listbase_clear(lb);
}
-static void ED_armature_ebone_listbase_copy(ListBase *lb_dst, ListBase *lb_src)
+void ED_armature_ebone_listbase_copy(ListBase *lb_dst, ListBase *lb_src)
{
EditBone *ebone_src;
EditBone *ebone_dst;
@@ -766,78 +776,6 @@ void ED_armature_ebone_listbase_temp_clear(ListBase *lb)
}
}
-typedef struct UndoArmature {
- EditBone *act_edbone;
- ListBase lb;
-} UndoArmature;
-
-static void undoBones_to_editBones(void *uarmv, void *armv, void *UNUSED(data))
-{
- UndoArmature *uarm = uarmv;
- bArmature *arm = armv;
- EditBone *ebone;
-
- ED_armature_ebone_listbase_free(arm->edbo);
- ED_armature_ebone_listbase_copy(arm->edbo, &uarm->lb);
-
- /* active bone */
- if (uarm->act_edbone) {
- ebone = uarm->act_edbone;
- arm->act_edbone = ebone->temp.ebone;
- }
- else {
- arm->act_edbone = NULL;
- }
-
- ED_armature_ebone_listbase_temp_clear(arm->edbo);
-}
-
-static void *editBones_to_undoBones(void *armv, void *UNUSED(obdata))
-{
- bArmature *arm = armv;
- UndoArmature *uarm;
- EditBone *ebone;
-
- uarm = MEM_callocN(sizeof(UndoArmature), "listbase undo");
-
- ED_armature_ebone_listbase_copy(&uarm->lb, arm->edbo);
-
- /* active bone */
- if (arm->act_edbone) {
- ebone = arm->act_edbone;
- uarm->act_edbone = ebone->temp.ebone;
- }
-
- ED_armature_ebone_listbase_temp_clear(&uarm->lb);
-
- return uarm;
-}
-
-static void free_undoBones(void *uarmv)
-{
- UndoArmature *uarm = uarmv;
-
- ED_armature_ebone_listbase_free(&uarm->lb);
-
- MEM_freeN(uarm);
-}
-
-static void *get_armature_edit(bContext *C)
-{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_ARMATURE) {
- return obedit->data;
- }
- return NULL;
-}
-
-/* and this is all the undo system needs to know */
-void undo_push_armature(bContext *C, const char *name)
-{
- // XXX solve getdata()
- undo_editmode_push(C, name, get_armature_edit, free_undoBones, undoBones_to_editBones, editBones_to_undoBones, NULL);
-}
-
/* *************************************************************** */
/* Low level selection functions which hide connected-parent
* flag behavior which gets tricky to handle in selection operators.
diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c
index 2fb216c2ef8..3dd41f25e09 100644
--- a/source/blender/editors/armature/editarmature_retarget.c
+++ b/source/blender/editors/armature/editarmature_retarget.c
@@ -42,7 +42,7 @@
#include "BKE_context.h"
#include "ED_armature.h"
-#include "ED_util.h"
+#include "ED_undo.h"
#include "BIF_retarget.h"
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index f4bebfd85e0..1f1468a8e41 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -158,7 +158,7 @@ void BIF_makeListTemplates(const bContext *C)
TEMPLATES_HASH = BLI_ghash_int_new("makeListTemplates gh");
TEMPLATES_CURRENT = 0;
- FOREACH_OBJECT(view_layer, ob)
+ FOREACH_OBJECT_BEGIN(view_layer, ob)
{
if (ob != obedit && ob->type == OB_ARMATURE) {
index++;
@@ -169,7 +169,7 @@ void BIF_makeListTemplates(const bContext *C)
}
}
}
- FOREACH_OBJECT_END
+ FOREACH_OBJECT_END;
}
#if 0 /* UNUSED */
@@ -178,7 +178,7 @@ const char *BIF_listTemplates(const bContext *UNUSED(C))
GHashIterator ghi;
const char *menu_header = IFACE_("Template %t|None %x0|");
char *p;
- const size_t template_size = (BLI_ghash_size(TEMPLATES_HASH) * 32 + 30);
+ const size_t template_size = (BLI_ghash_len(TEMPLATES_HASH) * 32 + 30);
if (TEMPLATES_MENU != NULL) {
MEM_freeN(TEMPLATES_MENU);
@@ -998,7 +998,7 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S
* the ideal would be to call this function only at the beginning of the snap operation,
* or at the beginning of the operator itself */
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), CTX_data_engine_type(C), 0,
+ CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), 0,
CTX_wm_region(C), CTX_wm_view3d(C));
float mvalf[2] = {UNPACK2(dd->mval)};
@@ -1932,7 +1932,7 @@ static bool sk_selectStroke(bContext *C, SK_Sketch *sketch, const int mval[2], c
short hits;
CTX_data_eval_ctx(C, &eval_ctx);
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
BLI_rcti_init_pt_radius(&rect, mval, 5);
@@ -2031,7 +2031,7 @@ static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch,
gpuPushMatrix();
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
switch (sketch->next_point.mode) {
case PT_SNAP:
diff --git a/source/blender/editors/armature/editarmature_undo.c b/source/blender/editors/armature/editarmature_undo.c
new file mode 100644
index 00000000000..217de06d99b
--- /dev/null
+++ b/source/blender/editors/armature/editarmature_undo.c
@@ -0,0 +1,192 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2002-2009 full recode.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/armature/editarmature_undo.c
+ * \ingroup edarmature
+ */
+
+#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_array_utils.h"
+
+#include "BKE_context.h"
+#include "BKE_undo_system.h"
+
+#include "DEG_depsgraph.h"
+
+#include "ED_armature.h"
+#include "ED_object.h"
+#include "ED_util.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Undo Conversion
+ * \{ */
+
+typedef struct UndoArmature {
+ EditBone *act_edbone;
+ ListBase lb;
+ size_t undo_size;
+} UndoArmature;
+
+static void undoarm_to_editarm(UndoArmature *uarm, bArmature *arm)
+{
+ EditBone *ebone;
+
+ ED_armature_ebone_listbase_free(arm->edbo);
+ ED_armature_ebone_listbase_copy(arm->edbo, &uarm->lb);
+
+ /* active bone */
+ if (uarm->act_edbone) {
+ ebone = uarm->act_edbone;
+ arm->act_edbone = ebone->temp.ebone;
+ }
+ else {
+ arm->act_edbone = NULL;
+ }
+
+ ED_armature_ebone_listbase_temp_clear(arm->edbo);
+}
+
+static void *undoarm_from_editarm(UndoArmature *uarm, bArmature *arm)
+{
+ BLI_assert(BLI_array_is_zeroed(uarm, 1));
+
+ /* TODO: include size of ID-properties. */
+ uarm->undo_size = 0;
+
+ ED_armature_ebone_listbase_copy(&uarm->lb, arm->edbo);
+
+ /* active bone */
+ if (arm->act_edbone) {
+ EditBone *ebone = arm->act_edbone;
+ uarm->act_edbone = ebone->temp.ebone;
+ }
+
+ ED_armature_ebone_listbase_temp_clear(&uarm->lb);
+
+ for (EditBone *ebone = uarm->lb.first; ebone; ebone = ebone->next) {
+ uarm->undo_size += sizeof(EditBone);
+ }
+
+ return uarm;
+}
+
+static void undoarm_free_data(UndoArmature *uarm)
+{
+ ED_armature_ebone_listbase_free(&uarm->lb);
+}
+
+static Object *editarm_object_from_context(bContext *C)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_ARMATURE) {
+ bArmature *arm = obedit->data;
+ if (arm->edbo != NULL) {
+ return obedit;
+ }
+ }
+ return NULL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Implements ED Undo System
+ * \{ */
+
+typedef struct ArmatureUndoStep {
+ UndoStep step;
+ /* note: will split out into list for multi-object-editmode. */
+ UndoRefID_Object obedit_ref;
+ UndoArmature data;
+} ArmatureUndoStep;
+
+static bool armature_undosys_poll(bContext *C)
+{
+ return editarm_object_from_context(C) != NULL;
+}
+
+static bool armature_undosys_step_encode(struct bContext *C, UndoStep *us_p)
+{
+ ArmatureUndoStep *us = (ArmatureUndoStep *)us_p;
+ us->obedit_ref.ptr = editarm_object_from_context(C);
+ bArmature *arm = us->obedit_ref.ptr->data;
+ undoarm_from_editarm(&us->data, arm);
+ us->step.data_size = us->data.undo_size;
+ return true;
+}
+
+static void armature_undosys_step_decode(struct bContext *C, UndoStep *us_p, int UNUSED(dir))
+{
+ /* TODO(campbell): undo_system: use low-level API to set mode. */
+ ED_object_mode_set(C, OB_MODE_EDIT);
+ BLI_assert(armature_undosys_poll(C));
+
+ ArmatureUndoStep *us = (ArmatureUndoStep *)us_p;
+ Object *obedit = us->obedit_ref.ptr;
+ bArmature *arm = obedit->data;
+ undoarm_to_editarm(&us->data, arm);
+ DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+}
+
+static void armature_undosys_step_free(UndoStep *us_p)
+{
+ ArmatureUndoStep *us = (ArmatureUndoStep *)us_p;
+ undoarm_free_data(&us->data);
+}
+
+static void armature_undosys_foreach_ID_ref(
+ UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+{
+ ArmatureUndoStep *us = (ArmatureUndoStep *)us_p;
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->obedit_ref));
+}
+
+/* Export for ED_undo_sys. */
+void ED_armature_undosys_type(UndoType *ut)
+{
+ ut->name = "Edit Armature";
+ ut->poll = armature_undosys_poll;
+ ut->step_encode = armature_undosys_step_encode;
+ ut->step_decode = armature_undosys_step_decode;
+ ut->step_free = armature_undosys_step_free;
+
+ ut->step_foreach_ID_ref = armature_undosys_foreach_ID_ref;
+
+ ut->mode = BKE_UNDOTYPE_MODE_STORE;
+ ut->use_context = true;
+
+ ut->step_size = sizeof(ArmatureUndoStep);
+}
+
+/** \} */
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 9500fd59b8b..489940007e4 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -46,6 +46,8 @@
#include "ED_mesh.h"
#include "ED_armature.h"
+#include "DEG_depsgraph.h"
+
#include "eigen_capi.h"
#include "meshlaplacian.h"
@@ -600,9 +602,10 @@ static float heat_limit_weight(float weight)
return weight;
}
-void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
- bDeformGroup **dgrouplist, bDeformGroup **dgroupflip,
- float (*root)[3], float (*tip)[3], int *selected, const char **err_str)
+void heat_bone_weighting(
+ Object *ob, Mesh *me, float (*verts)[3], int numsource,
+ bDeformGroup **dgrouplist, bDeformGroup **dgroupflip,
+ float (*root)[3], float (*tip)[3], int *selected, const char **err_str)
{
LaplacianSystem *sys;
MLoopTri *mlooptri;
diff --git a/source/blender/editors/armature/meshlaplacian.h b/source/blender/editors/armature/meshlaplacian.h
index bba8c739abf..05ade4fc43e 100644
--- a/source/blender/editors/armature/meshlaplacian.h
+++ b/source/blender/editors/armature/meshlaplacian.h
@@ -52,10 +52,11 @@ float laplacian_system_get_solution(LaplacianSystem *sys, int v);
/* Heat Weighting */
-void heat_bone_weighting(struct Object *ob, struct Mesh *me, float (*verts)[3],
- int numbones, struct bDeformGroup **dgrouplist,
- struct bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3],
- int *selected, const char **error);
+void heat_bone_weighting(
+ struct Object *ob, struct Mesh *me, float (*verts)[3],
+ int numbones, struct bDeformGroup **dgrouplist,
+ struct bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3],
+ int *selected, const char **error);
#ifdef RIGID_DEFORM
/* As-Rigid-As-Possible Deformation */
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index 74e29b2e8da..520ecc797aa 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -82,46 +82,62 @@ Object *ED_pose_object_from_context(bContext *C)
}
/* This function is used to process the necessary updates for */
-void ED_armature_enter_posemode(bContext *C, Base *base)
+bool ED_object_posemode_enter_ex(struct Main *bmain, Object *ob)
{
- ReportList *reports = CTX_wm_reports(C);
- Object *ob = base->object;
-
- if (ID_IS_LINKED(ob)) {
- BKE_report(reports, RPT_WARNING, "Cannot pose libdata");
- return;
- }
+ BLI_assert(!ID_IS_LINKED(ob));
+ bool ok = false;
switch (ob->type) {
case OB_ARMATURE:
ob->restore_mode = ob->mode;
ob->mode |= OB_MODE_POSE;
/* Inform all CoW versions that we changed the mode. */
- DEG_id_tag_update_ex(CTX_data_main(C), &ob->id, DEG_TAG_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL);
-
+ DEG_id_tag_update_ex(bmain, &ob->id, DEG_TAG_COPY_ON_WRITE);
+ ok = true;
+
break;
default:
- return;
+ break;
}
-
- /* XXX: disabled as this would otherwise cause a nasty loop... */
- //ED_object_toggle_modes(C, ob->mode);
+
+ return ok;
+}
+bool ED_object_posemode_enter(bContext *C, Object *ob)
+{
+ ReportList *reports = CTX_wm_reports(C);
+ if (ID_IS_LINKED(ob)) {
+ BKE_report(reports, RPT_WARNING, "Cannot pose libdata");
+ return false;
+ }
+ struct Main *bmain = CTX_data_main(C);
+ bool ok = ED_object_posemode_enter_ex(bmain, ob);
+ if (ok) {
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL);
+ }
+ return ok;
}
-void ED_armature_exit_posemode(bContext *C, Base *base)
+bool ED_object_posemode_exit_ex(struct Main *bmain, Object *ob)
{
- if (base) {
- Object *ob = base->object;
-
+ bool ok = false;
+ if (ob) {
ob->restore_mode = ob->mode;
ob->mode &= ~OB_MODE_POSE;
/* Inform all CoW versions that we changed the mode. */
- DEG_id_tag_update_ex(CTX_data_main(C), &ob->id, DEG_TAG_COPY_ON_WRITE);
-
+ DEG_id_tag_update_ex(bmain, &ob->id, DEG_TAG_COPY_ON_WRITE);
+ ok = true;
+ }
+ return ok;
+}
+bool ED_object_posemode_exit(bContext *C, Object *ob)
+{
+ struct Main *bmain = CTX_data_main(C);
+ bool ok = ED_object_posemode_exit_ex(bmain, ob);
+ if (ok) {
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
}
+ return ok;
}
/* if a selected or active bone is protected, throw error (oonly if warn == 1) and return 1 */
@@ -597,7 +613,7 @@ static void pose_copy_menu(Scene *scene)
/* ********************************************** */
-static int pose_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
+static int pose_flip_names_exec(bContext *C, wmOperator *op)
{
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
bArmature *arm;
@@ -606,6 +622,8 @@ static int pose_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
+ const bool do_strip_numbers = RNA_boolean_get(op->ptr, "do_strip_numbers");
+
arm = ob->data;
ListBase bones_names = {NULL};
@@ -616,7 +634,7 @@ static int pose_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
}
CTX_DATA_END;
- ED_armature_bones_flip_names(arm, &bones_names);
+ ED_armature_bones_flip_names(arm, &bones_names, do_strip_numbers);
BLI_freelistN(&bones_names);
@@ -642,6 +660,10 @@ void POSE_OT_flip_names(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "do_strip_numbers", false, "Strip Numbers",
+ "Try to remove right-most dot-number from flipped names "
+ "(WARNING: may result in incoherent naming in some cases)");
}
/* ------------------ */
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index d89b2fcfe84..54c40621a14 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -834,7 +834,6 @@ typedef struct tPoseLib_PreviewData {
bAction *act; /* poselib to use */
TimeMarker *marker; /* 'active' pose */
- int selcount; /* number of selected elements to work on */
int totcount; /* total number of elements to work on */
short state; /* state of main loop */
@@ -867,7 +866,8 @@ enum {
/* defines for tPoseLib_PreviewData->flag values */
enum {
PL_PREVIEW_FIRSTTIME = (1 << 0),
- PL_PREVIEW_SHOWORIGINAL = (1 << 1)
+ PL_PREVIEW_SHOWORIGINAL = (1 << 1),
+ PL_PREVIEW_ANY_BONE_SELECTED = (1 << 2),
};
/* ---------------------------- */
@@ -887,7 +887,20 @@ static void poselib_backup_posecopy(tPoseLib_PreviewData *pld)
{
bActionGroup *agrp;
bPoseChannel *pchan;
-
+ bool selected = false;
+
+ /* determine whether any bone is selected. */
+ LISTBASE_FOREACH (bPoseChannel *, bchan, &pld->pose->chanbase) {
+ selected = bchan->bone != NULL && bchan->bone->flag & BONE_SELECTED;
+ if (selected) {
+ pld->flag |= PL_PREVIEW_ANY_BONE_SELECTED;
+ break;
+ }
+ }
+ if (!selected) {
+ pld->flag &= ~PL_PREVIEW_ANY_BONE_SELECTED;
+ }
+
/* for each posechannel that has an actionchannel in */
for (agrp = pld->act->groups.first; agrp; agrp = agrp->next) {
/* try to find posechannel */
@@ -909,8 +922,6 @@ static void poselib_backup_posecopy(tPoseLib_PreviewData *pld)
BLI_addtail(&pld->backups, plb);
/* mark as being affected */
- if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))
- pld->selcount++;
pld->totcount++;
}
}
@@ -971,6 +982,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld)
KeyframeEditData ked = {{NULL}};
KeyframeEditFunc group_ok_cb;
int frame = 1;
+ const bool any_bone_selected = pld->flag & PL_PREVIEW_ANY_BONE_SELECTED;
/* get the frame */
if (pld->marker)
@@ -983,8 +995,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld)
group_ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
ked.f1 = ((float)frame) - 0.5f;
ked.f2 = ((float)frame) + 0.5f;
-
-
+
/* start applying - only those channels which have a key at this point in time! */
for (agrp = act->groups.first; agrp; agrp = agrp->next) {
/* check if group has any keyframes */
@@ -996,7 +1007,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld)
bool ok = 0;
/* check if this bone should get any animation applied */
- if (pld->selcount == 0) {
+ if (!any_bone_selected) {
/* if no bones are selected, then any bone is ok */
ok = 1;
}
@@ -1009,7 +1020,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld)
ok = 1;
}
}
-
+
if (ok)
animsys_evaluate_action_group(ptr, act, agrp, NULL, (float)frame);
}
@@ -1028,14 +1039,15 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData
KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
ListBase dsources = {NULL, NULL};
bool autokey = autokeyframe_cfra_can_key(scene, &pld->ob->id);
-
+ const bool any_bone_selected = pld->flag & PL_PREVIEW_ANY_BONE_SELECTED;
+
/* start tagging/keying */
for (agrp = act->groups.first; agrp; agrp = agrp->next) {
/* only for selected bones unless there aren't any selected, in which case all are included */
pchan = BKE_pose_channel_find_name(pose, agrp->name);
if (pchan) {
- if ((pld->selcount == 0) || ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))) {
+ if (!any_bone_selected || ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))) {
if (autokey) {
/* add datasource override for the PoseChannel, to be used later */
ANIM_relative_keyingset_add_source(&dsources, &pld->ob->id, &RNA_PoseBone, pchan);
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index 9bc678cd9e6..a66cedd8d4f 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -134,7 +134,7 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select)
/* called from editview.c, for mode-less pose selection */
/* assumes scene obact and basact is still on old situation */
bool ED_do_pose_selectbuffer(
- Scene *scene, ViewLayer *view_layer, Base *base, const unsigned int *buffer, short hits,
+ ViewLayer *view_layer, Base *base, const unsigned int *buffer, short hits,
bool extend, bool deselect, bool toggle, bool do_nearest)
{
Object *ob = base->object;
@@ -142,11 +142,13 @@ bool ED_do_pose_selectbuffer(
if (!ob || !ob->pose) return 0;
- nearBone = get_bone_from_selectbuffer(scene, base, buffer, hits, 1, do_nearest);
+ Object *ob_act = OBACT(view_layer);
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
+
+ nearBone = get_bone_from_selectbuffer(base, obedit, buffer, hits, 1, do_nearest);
/* if the bone cannot be affected, don't do anything */
if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) {
- Object *ob_act = OBACT(view_layer);
bArmature *arm = ob->data;
/* since we do unified select, we don't shift+select a bone if the
@@ -228,7 +230,7 @@ void ED_pose_de_selectall(Object *ob, int select_mode, const bool ignore_visibil
return;
}
- /* Determine if we're selecting or deselecting */
+ /* Determine if we're selecting or deselecting */
if (select_mode == SEL_TOGGLE) {
select_mode = SEL_SELECT;
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index 18d6408f026..c49591be5d1 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -158,6 +158,28 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
curbone->roll = eul[1];
}
+ /* combine pose and rest values for bendy bone settings,
+ * then clear the pchan values (so we don't get a double-up)
+ */
+ if (pchan->bone->segments > 1) {
+ curbone->curveInX += pchan->curveInX;
+ curbone->curveInY += pchan->curveInY;
+ curbone->curveOutX += pchan->curveOutX;
+ curbone->curveOutY += pchan->curveOutY;
+ curbone->roll1 += pchan->roll1;
+ curbone->roll2 += pchan->roll2;
+ curbone->ease1 += pchan->ease1;
+ curbone->ease2 += pchan->ease2;
+ curbone->scaleIn += pchan->scaleIn;
+ curbone->scaleOut += pchan->scaleOut;
+
+ pchan->curveInX = pchan->curveOutX = 0.0f;
+ pchan->curveInY = pchan->curveOutY = 0.0f;
+ pchan->roll1 = pchan->roll2 = 0.0f;
+ pchan->ease1 = pchan->ease2 = 0.0f;
+ pchan->scaleIn = pchan->scaleOut = 1.0f;
+ }
+
/* clear transform values for pchan */
zero_v3(pchan->loc);
zero_v3(pchan->eul);
@@ -510,7 +532,7 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
/* Make sure data from this file is usable for pose paste. */
- if (BLI_listbase_count_ex(&tmp_bmain->object, 2) != 1) {
+ if (BLI_listbase_count_at_most(&tmp_bmain->object, 2) != 1) {
BKE_report(op->reports, RPT_ERROR, "Copy buffer is not from pose mode");
BKE_main_free(tmp_bmain);
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c
index 0eb44085bae..fda7012e955 100644
--- a/source/blender/editors/armature/reeb.c
+++ b/source/blender/editors/armature/reeb.c
@@ -546,7 +546,7 @@ void verifyFaces(ReebGraph *rg)
int total = 0;
ReebArc *arc = NULL;
for (arc = rg->arcs.first; arc; arc = arc->next) {
- total += BLI_ghash_size(arc->faces);
+ total += BLI_ghash_len(arc->faces);
}
#endif
@@ -1656,7 +1656,7 @@ int filterSmartReebGraph(ReebGraph *UNUSED(rg), float UNUSED(threshold))
{
GHashIterator ghi;
int merging = 0;
- int total = BLI_ghash_size(arc->faces);
+ int total = BLI_ghash_len(arc->faces);
float avg_angle = 0;
float avg_vec[3] = {0, 0, 0};
@@ -1932,7 +1932,7 @@ void REEB_exportGraph(ReebGraph *rg, int count)
add_v3_v3v3(p, arc->tail->p, arc->head->p);
mul_v3_fl(p, 0.5f);
- fprintf(f, "angle %0.3f %0.3f %0.3f %0.3f %i\n", p[0], p[1], p[2], arc->angle, BLI_ghash_size(arc->faces));
+ fprintf(f, "angle %0.3f %0.3f %0.3f %0.3f %i\n", p[0], p[1], p[2], arc->angle, BLI_ghash_len(arc->faces));
exportNode(f, "v2", arc->tail);
}
@@ -2678,7 +2678,7 @@ static void shortestPathsFromVert(EditMesh *em, EditVert *starting_vert, EdgeInd
eed->f1 = 0;
}
- while (BLI_heap_size(edge_heap) > 0) {
+ while (BLI_heap_len(edge_heap) > 0) {
float current_weight;
current_eve->f1 = 1; /* mark vertex as selected */
@@ -2695,7 +2695,7 @@ static void shortestPathsFromVert(EditMesh *em, EditVert *starting_vert, EdgeInd
/* Find next shortest edge with unselected verts */
do {
current_weight = BLI_heap_node_value(BLI_heap_top(edge_heap));
- select_eed = BLI_heap_popmin(edge_heap);
+ select_eed = BLI_heap_pop_min(edge_heap);
} while (select_eed != NULL && select_eed->v1->f1 != 0 && select_eed->v2->f1);
if (select_eed != NULL) {
diff --git a/source/blender/editors/curve/CMakeLists.txt b/source/blender/editors/curve/CMakeLists.txt
index ae5c0a13ced..85daa7e44e5 100644
--- a/source/blender/editors/curve/CMakeLists.txt
+++ b/source/blender/editors/curve/CMakeLists.txt
@@ -43,6 +43,7 @@ set(SRC
editcurve_add.c
editcurve_paint.c
editcurve_select.c
+ editcurve_undo.c
editfont.c
editfont_undo.c
diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h
index bf1e22ae170..020d34f2767 100644
--- a/source/blender/editors/curve/curve_intern.h
+++ b/source/blender/editors/curve/curve_intern.h
@@ -35,6 +35,7 @@
/* internal exports only */
struct ListBase;
struct EditNurb;
+struct GHash;
struct Object;
struct wmOperatorType;
struct ViewContext;
@@ -129,6 +130,10 @@ void CURVE_OT_cyclic_toggle(struct wmOperatorType *ot);
void CURVE_OT_match_texture_space(struct wmOperatorType *ot);
+/* exported for editcurve_undo.c */
+struct GHash *ED_curve_keyindex_hash_duplicate(struct GHash *keyindex);
+void ED_curve_keyindex_update_nurb(struct EditNurb *editnurb, struct Nurb *nu, struct Nurb *newnu);
+
bool ED_curve_pick_vert(
struct ViewContext *vc, short sel, const int mval[2],
struct Nurb **r_nurb, struct BezTriple **r_bezt, struct BPoint **r_bp, short *r_handle);
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 4b578ba389e..3ea8592ac3e 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -84,16 +84,6 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
-/* Undo stuff */
-typedef struct {
- ListBase nubase;
- int actvert;
- GHash *undoIndex;
- ListBase fcurves, drivers;
- int actnu;
- int flag;
-} UndoCurve;
-
void selectend_nurb(Object *obedit, enum eEndPoint_Types selfirst, bool doswap, bool selstatus);
static void adduplicateflagNurb(Object *obedit, ListBase *newnurb, const short flag, const bool split);
static int curve_delete_segments(Object *obedit, const bool split);
@@ -346,7 +336,7 @@ static void keyIndex_updateBP(EditNurb *editnurb, BPoint *bp,
keyIndex_updateCV(editnurb, (char *)bp, (char *)newbp, count, sizeof(BPoint));
}
-static void keyIndex_updateNurb(EditNurb *editnurb, Nurb *nu, Nurb *newnu)
+void ED_curve_keyindex_update_nurb(EditNurb *editnurb, Nurb *nu, Nurb *newnu)
{
if (nu->bezt) {
keyIndex_updateBezt(editnurb, nu->bezt, newnu->bezt, newnu->pntsu);
@@ -525,12 +515,12 @@ static void keyData_switchDirectionNurb(Curve *cu, Nurb *nu)
switch_keys_direction(cu, nu);
}
-static GHash *dupli_keyIndexHash(GHash *keyindex)
+GHash *ED_curve_keyindex_hash_duplicate(GHash *keyindex)
{
GHash *gh;
GHashIterator gh_iter;
- gh = BLI_ghash_ptr_new_ex("dupli_keyIndex gh", BLI_ghash_size(keyindex));
+ gh = BLI_ghash_ptr_new_ex("dupli_keyIndex gh", BLI_ghash_len(keyindex));
GHASH_ITER (gh_iter, keyindex) {
void *cv = BLI_ghashIterator_getKey(&gh_iter);
@@ -1242,7 +1232,10 @@ void ED_curve_editnurb_make(Object *obedit)
if (actkey) {
// XXX strcpy(G.editModeTitleExtra, "(Key) ");
+ /* TODO(campbell): undo_system: investigate why this was needed. */
+#if 0
undo_editmode_clear();
+#endif
}
if (editnurb) {
@@ -4312,7 +4305,7 @@ bool ED_curve_editnurb_select_pick(bContext *C, const int mval[2], bool extend,
short hand;
view3d_operator_needs_opengl(C);
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
location[0] = mval[0];
location[1] = mval[1];
@@ -4988,7 +4981,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewContext vc;
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
if (vc.rv3d && !RNA_struct_property_is_set(op->ptr, "location")) {
Curve *cu;
@@ -5020,14 +5013,13 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const float mval[2] = {UNPACK2(event->mval)};
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), vc.scene, vc.view_layer, vc.engine_type, 0,
- vc.ar, vc.v3d);
+ CTX_data_main(C), vc.scene, vc.view_layer, 0, vc.ar, vc.v3d);
ED_transform_snap_object_project_view3d_mixed(
snap_context,
SCE_SELECT_FACE,
&(const struct SnapObjectParams){
- .snap_select = (vc.scene->obedit != NULL) ? SNAP_NOT_ACTIVE : SNAP_ALL,
+ .snap_select = (vc.obedit != NULL) ? SNAP_NOT_ACTIVE : SNAP_ALL,
.use_object_edit_cage = false,
},
mval, NULL, true,
@@ -6202,119 +6194,6 @@ void CURVE_OT_tilt_clear(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/****************** undo for curves ****************/
-
-static void undoCurve_to_editCurve(void *ucu, void *UNUSED(edata), void *cu_v)
-{
- Curve *cu = cu_v;
- UndoCurve *undoCurve = ucu;
- ListBase *undobase = &undoCurve->nubase;
- ListBase *editbase = BKE_curve_editNurbs_get(cu);
- Nurb *nu, *newnu;
- EditNurb *editnurb = cu->editnurb;
- AnimData *ad = BKE_animdata_from_id(&cu->id);
-
- BKE_nurbList_free(editbase);
-
- if (undoCurve->undoIndex) {
- BKE_curve_editNurb_keyIndex_free(&editnurb->keyindex);
- editnurb->keyindex = dupli_keyIndexHash(undoCurve->undoIndex);
- }
-
- if (ad) {
- if (ad->action) {
- free_fcurves(&ad->action->curves);
- copy_fcurves(&ad->action->curves, &undoCurve->fcurves);
- }
-
- free_fcurves(&ad->drivers);
- copy_fcurves(&ad->drivers, &undoCurve->drivers);
- }
-
- /* copy */
- for (nu = undobase->first; nu; nu = nu->next) {
- newnu = BKE_nurb_duplicate(nu);
-
- if (editnurb->keyindex) {
- keyIndex_updateNurb(editnurb, nu, newnu);
- }
-
- BLI_addtail(editbase, newnu);
- }
-
- cu->actvert = undoCurve->actvert;
- cu->actnu = undoCurve->actnu;
- cu->flag = undoCurve->flag;
- ED_curve_updateAnimPaths(cu);
-}
-
-static void *editCurve_to_undoCurve(void *UNUSED(edata), void *cu_v)
-{
- Curve *cu = cu_v;
- ListBase *nubase = BKE_curve_editNurbs_get(cu);
- UndoCurve *undoCurve;
- EditNurb *editnurb = cu->editnurb, tmpEditnurb;
- Nurb *nu, *newnu;
- AnimData *ad = BKE_animdata_from_id(&cu->id);
-
- undoCurve = MEM_callocN(sizeof(UndoCurve), "undoCurve");
-
- if (editnurb->keyindex) {
- undoCurve->undoIndex = dupli_keyIndexHash(editnurb->keyindex);
- tmpEditnurb.keyindex = undoCurve->undoIndex;
- }
-
- if (ad) {
- if (ad->action)
- copy_fcurves(&undoCurve->fcurves, &ad->action->curves);
-
- copy_fcurves(&undoCurve->drivers, &ad->drivers);
- }
-
- /* copy */
- for (nu = nubase->first; nu; nu = nu->next) {
- newnu = BKE_nurb_duplicate(nu);
-
- if (undoCurve->undoIndex) {
- keyIndex_updateNurb(&tmpEditnurb, nu, newnu);
- }
-
- BLI_addtail(&undoCurve->nubase, newnu);
- }
-
- undoCurve->actvert = cu->actvert;
- undoCurve->actnu = cu->actnu;
- undoCurve->flag = cu->flag;
-
- return undoCurve;
-}
-
-static void free_undoCurve(void *ucv)
-{
- UndoCurve *undoCurve = ucv;
-
- BKE_nurbList_free(&undoCurve->nubase);
-
- BKE_curve_editNurb_keyIndex_free(&undoCurve->undoIndex);
-
- free_fcurves(&undoCurve->fcurves);
- free_fcurves(&undoCurve->drivers);
-
- MEM_freeN(undoCurve);
-}
-
-static void *get_data(bContext *C)
-{
- Object *obedit = CTX_data_edit_object(C);
- return obedit;
-}
-
-/* and this is all the undo system needs to know */
-void undo_push_curve(bContext *C, const char *name)
-{
- undo_editmode_push(C, name, get_data, free_undoCurve, undoCurve_to_editCurve, editCurve_to_undoCurve, NULL);
-}
-
void ED_curve_beztcpy(EditNurb *editnurb, BezTriple *dst, BezTriple *src, int count)
{
memcpy(dst, src, count * sizeof(BezTriple));
diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c
index 281f6c3c22e..f269799973f 100644
--- a/source/blender/editors/curve/editcurve_add.c
+++ b/source/blender/editors/curve/editcurve_add.c
@@ -53,7 +53,7 @@
#include "ED_object.h"
#include "ED_screen.h"
-#include "ED_util.h"
+#include "ED_undo.h"
#include "ED_view3d.h"
#include "ED_curve.h"
diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c
index 062b9c94a1b..36eb4c6c5bc 100644
--- a/source/blender/editors/curve/editcurve_paint.c
+++ b/source/blender/editors/curve/editcurve_paint.c
@@ -365,7 +365,7 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUS
wmOperator *op = arg;
struct CurveDrawData *cdd = op->customdata;
- const int stroke_len = BLI_mempool_count(cdd->stroke_elem_pool);
+ const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
if (stroke_len == 0) {
return;
@@ -608,7 +608,7 @@ static bool curve_draw_init(bContext *C, wmOperator *op, bool is_invoke)
cdd->depsgraph = CTX_data_depsgraph(C);
if (is_invoke) {
- view3d_set_viewcontext(C, &cdd->vc);
+ ED_view3d_viewcontext_init(C, &cdd->vc);
if (ELEM(NULL, cdd->vc.ar, cdd->vc.rv3d, cdd->vc.v3d, cdd->vc.win, cdd->vc.scene)) {
MEM_freeN(cdd);
BKE_report(op->reports, RPT_ERROR, "Unable to access 3D viewport");
@@ -706,7 +706,7 @@ static void curve_draw_exec_precalc(wmOperator *op)
if (!RNA_property_is_set(op->ptr, prop)) {
bool use_cyclic = false;
- if (BLI_mempool_count(cdd->stroke_elem_pool) > 2) {
+ if (BLI_mempool_len(cdd->stroke_elem_pool) > 2) {
BLI_mempool_iter iter;
const struct StrokeElem *selem, *selem_first, *selem_last;
@@ -732,7 +732,7 @@ static void curve_draw_exec_precalc(wmOperator *op)
(cps->radius_taper_end != 0.0f))
{
/* note, we could try to de-duplicate the length calculations above */
- const int stroke_len = BLI_mempool_count(cdd->stroke_elem_pool);
+ const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
BLI_mempool_iter iter;
struct StrokeElem *selem, *selem_prev;
@@ -788,18 +788,18 @@ static int curve_draw_exec(bContext *C, wmOperator *op)
struct CurveDrawData *cdd = op->customdata;
const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings;
- Object *obedit = cdd->vc.scene->obedit;
+ Object *obedit = cdd->vc.obedit;
Curve *cu = obedit->data;
ListBase *nurblist = object_editcurve_get(obedit);
- int stroke_len = BLI_mempool_count(cdd->stroke_elem_pool);
+ int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
const bool is_3d = (cu->flag & CU_3D) != 0;
invert_m4_m4(obedit->imat, obedit->obmat);
- if (BLI_mempool_count(cdd->stroke_elem_pool) == 0) {
+ if (BLI_mempool_len(cdd->stroke_elem_pool) == 0) {
curve_draw_stroke_from_operator(op);
- stroke_len = BLI_mempool_count(cdd->stroke_elem_pool);
+ stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
}
ED_curve_deselect_all(cu->editnurb);
diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c
index 02b8970731c..673faa37f2a 100644
--- a/source/blender/editors/curve/editcurve_select.c
+++ b/source/blender/editors/curve/editcurve_select.c
@@ -559,7 +559,7 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent
const bool select = !RNA_boolean_get(op->ptr, "deselect");
view3d_operator_needs_opengl(C);
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
if (!ED_curve_pick_vert(&vc, 1, event->mval, &nu, &bezt, &bp, NULL)) {
return OPERATOR_CANCELLED;
@@ -1607,7 +1607,7 @@ static void curve_select_shortest_path_surf(Nurb *nu, int vert_src, int vert_dst
int axis, sign;
int u, v;
- vert_curr = *((int *)BLI_heap_popmin(heap));
+ vert_curr = *((int *)BLI_heap_pop_min(heap));
if (vert_curr == vert_dst) {
break;
}
@@ -1677,7 +1677,7 @@ static int edcu_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE
}
view3d_operator_needs_opengl(C);
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
if (!ED_curve_pick_vert(&vc, 1, event->mval, &nu_dst, &bezt_dst, &bp_dst, NULL)) {
return OPERATOR_PASS_THROUGH;
diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c
new file mode 100644
index 00000000000..4eb2abaefad
--- /dev/null
+++ b/source/blender/editors/curve/editcurve_undo.c
@@ -0,0 +1,257 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/curve/editcurve_undo.c
+ * \ingroup edcurve
+ */
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_anim_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_array_utils.h"
+
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_fcurve.h"
+#include "BKE_library.h"
+#include "BKE_animsys.h"
+#include "BKE_undo_system.h"
+
+#include "DEG_depsgraph.h"
+
+#include "ED_object.h"
+#include "ED_util.h"
+#include "ED_curve.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+#include "curve_intern.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Undo Conversion
+ * \{ */
+
+typedef struct {
+ ListBase nubase;
+ int actvert;
+ GHash *undoIndex;
+ ListBase fcurves, drivers;
+ int actnu;
+ int flag;
+
+ /* Stored in the object, needed since users may change the active key while in edit-mode. */
+ struct {
+ short shapenr;
+ } obedit;
+
+ size_t undo_size;
+} UndoCurve;
+
+static void undocurve_to_editcurve(UndoCurve *ucu, Curve *cu, short *r_shapenr)
+{
+ ListBase *undobase = &ucu->nubase;
+ ListBase *editbase = BKE_curve_editNurbs_get(cu);
+ Nurb *nu, *newnu;
+ EditNurb *editnurb = cu->editnurb;
+ AnimData *ad = BKE_animdata_from_id(&cu->id);
+
+ BKE_nurbList_free(editbase);
+
+ if (ucu->undoIndex) {
+ BKE_curve_editNurb_keyIndex_free(&editnurb->keyindex);
+ editnurb->keyindex = ED_curve_keyindex_hash_duplicate(ucu->undoIndex);
+ }
+
+ if (ad) {
+ if (ad->action) {
+ free_fcurves(&ad->action->curves);
+ copy_fcurves(&ad->action->curves, &ucu->fcurves);
+ }
+
+ free_fcurves(&ad->drivers);
+ copy_fcurves(&ad->drivers, &ucu->drivers);
+ }
+
+ /* copy */
+ for (nu = undobase->first; nu; nu = nu->next) {
+ newnu = BKE_nurb_duplicate(nu);
+
+ if (editnurb->keyindex) {
+ ED_curve_keyindex_update_nurb(editnurb, nu, newnu);
+ }
+
+ BLI_addtail(editbase, newnu);
+ }
+
+ cu->actvert = ucu->actvert;
+ cu->actnu = ucu->actnu;
+ cu->flag = ucu->flag;
+ *r_shapenr = ucu->obedit.shapenr;
+ ED_curve_updateAnimPaths(cu);
+}
+
+static void undocurve_from_editcurve(UndoCurve *ucu, Curve *cu, const short shapenr)
+{
+ BLI_assert(BLI_array_is_zeroed(ucu, 1));
+ ListBase *nubase = BKE_curve_editNurbs_get(cu);
+ EditNurb *editnurb = cu->editnurb, tmpEditnurb;
+ Nurb *nu, *newnu;
+ AnimData *ad = BKE_animdata_from_id(&cu->id);
+
+ /* TODO: include size of fcurve & undoIndex */
+ // ucu->undo_size = 0;
+
+ if (editnurb->keyindex) {
+ ucu->undoIndex = ED_curve_keyindex_hash_duplicate(editnurb->keyindex);
+ tmpEditnurb.keyindex = ucu->undoIndex;
+ }
+
+ if (ad) {
+ if (ad->action)
+ copy_fcurves(&ucu->fcurves, &ad->action->curves);
+
+ copy_fcurves(&ucu->drivers, &ad->drivers);
+ }
+
+ /* copy */
+ for (nu = nubase->first; nu; nu = nu->next) {
+ newnu = BKE_nurb_duplicate(nu);
+
+ if (ucu->undoIndex) {
+ ED_curve_keyindex_update_nurb(&tmpEditnurb, nu, newnu);
+ }
+
+ BLI_addtail(&ucu->nubase, newnu);
+
+ ucu->undo_size += (
+ (nu->bezt ? (sizeof(BezTriple) * nu->pntsu) : 0) +
+ (nu->bp ? (sizeof(BPoint) * (nu->pntsu * nu->pntsv)) : 0) +
+ (nu->knotsu ? (sizeof(float) * KNOTSU(nu)) : 0) +
+ (nu->knotsv ? (sizeof(float) * KNOTSV(nu)) : 0) +
+ sizeof(Nurb));
+ }
+
+ ucu->actvert = cu->actvert;
+ ucu->actnu = cu->actnu;
+ ucu->flag = cu->flag;
+
+ ucu->obedit.shapenr = shapenr;
+}
+
+static void undocurve_free_data(UndoCurve *uc)
+{
+ BKE_nurbList_free(&uc->nubase);
+
+ BKE_curve_editNurb_keyIndex_free(&uc->undoIndex);
+
+ free_fcurves(&uc->fcurves);
+ free_fcurves(&uc->drivers);
+}
+
+static Object *editcurve_object_from_context(bContext *C)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ Curve *cu = obedit->data;
+ if (BKE_curve_editNurbs_get(cu) != NULL) {
+ return obedit;
+ }
+ }
+ return NULL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Implements ED Undo System
+ * \{ */
+
+typedef struct CurveUndoStep {
+ UndoStep step;
+ /* note: will split out into list for multi-object-editmode. */
+ UndoRefID_Object obedit_ref;
+ UndoCurve data;
+} CurveUndoStep;
+
+static bool curve_undosys_poll(bContext *C)
+{
+ Object *obedit = editcurve_object_from_context(C);
+ return (obedit != NULL);
+}
+
+static bool curve_undosys_step_encode(struct bContext *C, UndoStep *us_p)
+{
+ CurveUndoStep *us = (CurveUndoStep *)us_p;
+ us->obedit_ref.ptr = editcurve_object_from_context(C);
+ undocurve_from_editcurve(&us->data, us->obedit_ref.ptr->data, us->obedit_ref.ptr->shapenr);
+ us->step.data_size = us->data.undo_size;
+ return true;
+}
+
+static void curve_undosys_step_decode(struct bContext *C, UndoStep *us_p, int UNUSED(dir))
+{
+ /* TODO(campbell): undo_system: use low-level API to set mode. */
+ ED_object_mode_set(C, OB_MODE_EDIT);
+ BLI_assert(curve_undosys_poll(C));
+
+ CurveUndoStep *us = (CurveUndoStep *)us_p;
+ Object *obedit = us->obedit_ref.ptr;
+ undocurve_to_editcurve(&us->data, obedit->data, &obedit->shapenr);
+ DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+}
+
+static void curve_undosys_step_free(UndoStep *us_p)
+{
+ CurveUndoStep *us = (CurveUndoStep *)us_p;
+ undocurve_free_data(&us->data);
+}
+
+static void curve_undosys_foreach_ID_ref(
+ UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+{
+ CurveUndoStep *us = (CurveUndoStep *)us_p;
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->obedit_ref));
+}
+
+/* Export for ED_undo_sys. */
+void ED_curve_undosys_type(UndoType *ut)
+{
+ ut->name = "Edit Curve";
+ ut->poll = curve_undosys_poll;
+ ut->step_encode = curve_undosys_step_encode;
+ ut->step_decode = curve_undosys_step_decode;
+ ut->step_free = curve_undosys_step_free;
+
+ ut->step_foreach_ID_ref = curve_undosys_foreach_ID_ref;
+
+ ut->mode = BKE_UNDOTYPE_MODE_STORE;
+ ut->use_context = true;
+
+ ut->step_size = sizeof(CurveUndoStep);
+}
+
+/** \} */
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index cbb5abf1309..b72ac8c63c8 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -1857,7 +1857,7 @@ bool ED_curve_editfont_select_pick(bContext *C, const int mval[2], bool extend,
const float dist = ED_view3d_select_dist_px();
float dist_sq_best = dist * dist;
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c
index a61f863b61e..d4d48e93f43 100644
--- a/source/blender/editors/curve/editfont_undo.c
+++ b/source/blender/editors/curve/editfont_undo.c
@@ -29,6 +29,8 @@
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
+#include "BLI_array_utils.h"
+
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
@@ -36,10 +38,17 @@
#include "BKE_context.h"
#include "BKE_font.h"
+#include "BKE_undo_system.h"
+
+#include "DEG_depsgraph.h"
+#include "ED_object.h"
#include "ED_curve.h"
#include "ED_util.h"
+#include "WM_types.h"
+#include "WM_api.h"
+
#define USE_ARRAY_STORE
#ifdef USE_ARRAY_STORE
@@ -50,6 +59,10 @@
# define ARRAY_CHUNK_SIZE 32
#endif
+/* -------------------------------------------------------------------- */
+/** \name Undo Conversion
+ * \{ */
+
typedef struct UndoFont {
wchar_t *textbuf;
struct CharInfo *textbufinfo;
@@ -62,6 +75,8 @@ typedef struct UndoFont {
BArrayState *textbufinfo;
} store;
#endif
+
+ size_t undo_size;
} UndoFont;
@@ -202,23 +217,20 @@ static void uf_arraystore_free(UndoFont *uf)
BLI_array_store_at_size_clear(&uf_arraystore.bs_stride);
}
-
}
/** \} */
#endif /* USE_ARRAY_STORE */
-static void undoFont_to_editFont(void *uf_v, void *ecu, void *UNUSED(obdata))
+static void undofont_to_editfont(UndoFont *uf, Curve *cu)
{
- Curve *cu = (Curve *)ecu;
EditFont *ef = cu->editfont;
- const UndoFont *uf = uf_v;
size_t final_size;
#ifdef USE_ARRAY_STORE
- uf_arraystore_expand(uf_v);
+ uf_arraystore_expand(uf);
#endif
final_size = sizeof(wchar_t) * (uf->len + 1);
@@ -233,16 +245,17 @@ static void undoFont_to_editFont(void *uf_v, void *ecu, void *UNUSED(obdata))
ef->selstart = ef->selend = 0;
#ifdef USE_ARRAY_STORE
- uf_arraystore_expand_clear(uf_v);
+ uf_arraystore_expand_clear(uf);
#endif
}
-static void *editFont_to_undoFont(void *ecu, void *UNUSED(obdata))
+static void *undofont_from_editfont(UndoFont *uf, Curve *cu)
{
- Curve *cu = (Curve *)ecu;
+ BLI_assert(BLI_array_is_zeroed(uf, 1));
+
EditFont *ef = cu->editfont;
- UndoFont *uf = MEM_callocN(sizeof(*uf), __func__);
+ size_t mem_used_prev = MEM_get_memory_in_use();
size_t final_size;
@@ -269,13 +282,15 @@ static void *editFont_to_undoFont(void *ecu, void *UNUSED(obdata))
}
#endif
+ size_t mem_used_curr = MEM_get_memory_in_use();
+
+ uf->undo_size = mem_used_prev < mem_used_curr ? mem_used_curr - mem_used_prev : sizeof(UndoFont);
+
return uf;
}
-static void free_undoFont(void *uf_v)
+static void undofont_free_data(UndoFont *uf)
{
- UndoFont *uf = uf_v;
-
#ifdef USE_ARRAY_STORE
{
LinkData *link = BLI_findptr(&uf_arraystore.local_links, uf, offsetof(LinkData, data));
@@ -291,21 +306,91 @@ static void free_undoFont(void *uf_v)
if (uf->textbufinfo) {
MEM_freeN(uf->textbufinfo);
}
-
- MEM_freeN(uf);
}
-static void *get_undoFont(bContext *C)
+static Object *editfont_object_from_context(bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
if (obedit && obedit->type == OB_FONT) {
- return obedit->data;
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+ if (ef != NULL) {
+ return obedit;
+ }
}
return NULL;
}
-/* and this is all the undo system needs to know */
-void undo_push_font(bContext *C, const char *name)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Implements ED Undo System
+ * \{ */
+
+typedef struct FontUndoStep {
+ UndoStep step;
+ /* note: will split out into list for multi-object-editmode. */
+ UndoRefID_Object obedit_ref;
+ UndoFont data;
+} FontUndoStep;
+
+static bool font_undosys_poll(bContext *C)
{
- undo_editmode_push(C, name, get_undoFont, free_undoFont, undoFont_to_editFont, editFont_to_undoFont, NULL);
+ return editfont_object_from_context(C) != NULL;
}
+
+static bool font_undosys_step_encode(struct bContext *C, UndoStep *us_p)
+{
+ FontUndoStep *us = (FontUndoStep *)us_p;
+ us->obedit_ref.ptr = editfont_object_from_context(C);
+ Curve *cu = us->obedit_ref.ptr->data;
+ undofont_from_editfont(&us->data, cu);
+ us->step.data_size = us->data.undo_size;
+ return true;
+}
+
+static void font_undosys_step_decode(struct bContext *C, UndoStep *us_p, int UNUSED(dir))
+{
+ /* TODO(campbell): undo_system: use low-level API to set mode. */
+ ED_object_mode_set(C, OB_MODE_EDIT);
+ BLI_assert(font_undosys_poll(C));
+
+ FontUndoStep *us = (FontUndoStep *)us_p;
+ Object *obedit = us->obedit_ref.ptr;
+ Curve *cu = obedit->data;
+ undofont_to_editfont(&us->data, cu);
+ DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+}
+
+static void font_undosys_step_free(UndoStep *us_p)
+{
+ FontUndoStep *us = (FontUndoStep *)us_p;
+ undofont_free_data(&us->data);
+}
+
+static void font_undosys_foreach_ID_ref(
+ UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+{
+ FontUndoStep *us = (FontUndoStep *)us_p;
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->obedit_ref));
+}
+
+/* Export for ED_undo_sys. */
+void ED_font_undosys_type(UndoType *ut)
+{
+ ut->name = "Edit Font";
+ ut->poll = font_undosys_poll;
+ ut->step_encode = font_undosys_step_encode;
+ ut->step_decode = font_undosys_step_decode;
+ ut->step_free = font_undosys_step_free;
+
+ ut->step_foreach_ID_ref = font_undosys_foreach_ID_ref;
+
+ ut->mode = BKE_UNDOTYPE_MODE_STORE;
+ ut->use_context = true;
+
+ ut->step_size = sizeof(FontUndoStep);
+}
+
+/** \} */
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 4a95027528b..942aa861cec 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -41,7 +41,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_polyfill2d.h"
+#include "BLI_polyfill_2d.h"
#include "BLF_api.h"
#include "BLT_translation.h"
@@ -1479,7 +1479,7 @@ static void gp_draw_status_text(const bGPdata *gpd, ARegion *ar)
/* grease pencil icon... */
// XXX: is this too intrusive?
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
xco -= U.widget_unit;
diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c
index 38927cf91e1..533ab21dbb6 100644
--- a/source/blender/editors/gpencil/gpencil_brush.c
+++ b/source/blender/editors/gpencil/gpencil_brush.c
@@ -54,7 +54,6 @@
#include "DNA_object_types.h"
#include "BKE_context.h"
-#include "BKE_global.h"
#include "BKE_gpencil.h"
#include "BKE_library.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index d2ae8bc3ce7..2c3c9f4f9b9 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -55,6 +55,7 @@
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_workspace_types.h"
#include "BKE_collection.h"
#include "BKE_context.h"
@@ -1293,6 +1294,7 @@ static int gp_convert_poll(bContext *C)
bGPDframe *gpf = NULL;
ScrArea *sa = CTX_wm_area(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
/* only if the current view is 3D View, if there's valid data (i.e. at least one stroke!),
* and if we are not in edit mode!
@@ -1301,7 +1303,7 @@ static int gp_convert_poll(bContext *C)
(gpl = BKE_gpencil_layer_getactive(gpd)) &&
(gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0)) &&
(gpf->strokes.first) &&
- (scene->obedit == NULL));
+ (OBEDIT_FROM_VIEW_LAYER(view_layer) == NULL));
}
static int gp_convert_layer_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index 5bd5c9c74b9..9d183222c2d 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -53,7 +53,6 @@
#include "DNA_gpencil_types.h"
#include "BKE_context.h"
-#include "BKE_global.h"
#include "BKE_gpencil.h"
#include "BKE_library.h"
#include "BKE_object.h"
@@ -1063,7 +1062,7 @@ static int gp_brush_remove_exec(bContext *C, wmOperator *op)
if (ELEM(NULL, ts, brush))
return OPERATOR_CANCELLED;
- if (BLI_listbase_count_ex(&ts->gp_brushes, 2) < 2) {
+ if (BLI_listbase_count_at_most(&ts->gp_brushes, 2) < 2) {
BKE_report(op->reports, RPT_ERROR, "Grease Pencil needs a brush, unable to delete the last one");
return OPERATOR_CANCELLED;
}
@@ -1421,7 +1420,7 @@ static int gp_palette_remove_exec(bContext *C, wmOperator *op)
if (ELEM(NULL, gpd, palette))
return OPERATOR_CANCELLED;
- if (BLI_listbase_count_ex(&gpd->palettes, 2) < 2) {
+ if (BLI_listbase_count_at_most(&gpd->palettes, 2) < 2) {
BKE_report(op->reports, RPT_ERROR, "Grease Pencil needs a palette, unable to delete the last one");
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 22a3224e563..1eee774fd3e 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -55,7 +55,6 @@
#include "DNA_gpencil_types.h"
#include "BKE_context.h"
-#include "BKE_global.h"
#include "BKE_gpencil.h"
#include "BKE_library.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 472b88cb18b..77e5dc8fe5d 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -46,7 +46,6 @@
#include "PIL_time.h"
-#include "BKE_main.h"
#include "BKE_paint.h"
#include "BKE_gpencil.h"
#include "BKE_context.h"
@@ -1862,7 +1861,7 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
immUniformColor4ub(255, 100, 100, 20);
imm_draw_circle_fill_2d(shdr_pos, x, y, p->radius, 40);
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index 07abab8af2e..dc3483163bf 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -37,7 +37,7 @@
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
-#include "BLI_lasso.h"
+#include "BLI_lasso_2d.h"
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c
index 7a9ad2b32c0..202d7630ae0 100644
--- a/source/blender/editors/gpencil/gpencil_undo.c
+++ b/source/blender/editors/gpencil/gpencil_undo.c
@@ -45,7 +45,6 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
-#include "BKE_main.h"
#include "ED_gpencil.h"
diff --git a/source/blender/editors/groom/editgroom_select.c b/source/blender/editors/groom/editgroom_select.c
index 190e121ea2b..9592d3e21fe 100644
--- a/source/blender/editors/groom/editgroom_select.c
+++ b/source/blender/editors/groom/editgroom_select.c
@@ -324,7 +324,7 @@ static void groom_set_section_select_flags(Groom *groom, int flag)
bool ED_groom_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
ViewContext vc;
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
Groom *groom = vc.obedit->data;
struct
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index 3184ebee4d9..863d817d19a 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -107,38 +107,6 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state,
float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY,
float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y,
float xzoom, float yzoom, float color[4]);
-/* 2D Drawing Assistance */
-
-/** Define a 2D area (viewport, scissor, matrices) for OpenGL rendering.
- *
- * glaDefine2DArea and glaBegin2DDraw set up an OpenGL state appropriate
- * for drawing using both vertex (Vertex, etc) and raster (RasterPos, Rect)
- * commands. All coordinates should be at integer positions. There is little
- * to no reason to use glVertex2f etc. functions during 2D rendering, and
- * thus no reason to +-0.5 the coordinates or perform other silly
- * tricks.
- *
- * \param screen_rect The screen rectangle to be defined for 2D drawing.
- */
-void glaDefine2DArea(struct rcti *screen_rect);
-
-/* TODO(merwin): put the following 2D code to use, or build new 2D code inspired & informd by it */
-
-#if 0 /* UNUSED */
-
-typedef struct gla2DDrawInfo gla2DDrawInfo;
-
-gla2DDrawInfo *glaBegin2DDraw(struct rcti *screen_rect, struct rctf *world_rect);
-void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *r_sc_x, int *r_sc_y);
-void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int r_screen[2]);
-
-void glaEnd2DDraw(gla2DDrawInfo *di);
-
-/** Adjust the transformation mapping of a 2d area */
-void gla2DGetMap(gla2DDrawInfo *di, struct rctf *rect);
-void gla2DSetMap(gla2DDrawInfo *di, struct rctf *rect);
-
-#endif /* UNUSED */
void set_inverted_drawing(int enable);
void setlinestyle(int nr);
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 4595bcfa86d..0dcc4f32e43 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -52,6 +52,7 @@ struct ViewContext;
struct wmKeyConfig;
struct wmOperator;
struct Main;
+struct UndoType;
typedef struct EditBone {
struct EditBone *next, *prev;
@@ -137,25 +138,26 @@ void ED_keymap_armature(struct wmKeyConfig *keyconf);
void ED_armature_from_edit(struct bArmature *arm);
void ED_armature_to_edit(struct bArmature *arm);
void ED_armature_edit_free(struct bArmature *arm);
-void ED_armature_ebone_listbase_temp_clear(struct ListBase *lb);
void ED_armature_deselect_all(struct Object *obedit);
void ED_armature_deselect_all_visible(struct Object *obedit);
bool ED_do_pose_selectbuffer(
- struct Scene *scene, struct ViewLayer *view_layer, struct Base *base, const unsigned int *buffer, short hits,
+ struct ViewLayer *view_layer, struct Base *base, const unsigned int *buffer, short hits,
bool extend, bool deselect, bool toggle, bool do_nearest);
bool ED_armature_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
int join_armature_exec(struct bContext *C, struct wmOperator *op);
struct Bone *get_indexed_bone(struct Object *ob, int index);
float ED_rollBoneToVector(EditBone *bone, const float new_up_axis[3], const bool axis_only);
-EditBone *ED_armature_bone_find_name(const ListBase *edbo, const char *name);
+EditBone *ED_armature_bone_find_name(const struct ListBase *edbo, const char *name);
EditBone *ED_armature_bone_get_mirrored(const struct ListBase *edbo, EditBone *ebo);
void ED_armature_sync_selection(struct ListBase *edbo);
void ED_armature_validate_active(struct bArmature *arm);
EditBone *ED_armature_edit_bone_add_primitive(struct Object *obedit_arm, float length, bool view_aligned);
EditBone *ED_armature_edit_bone_add(struct bArmature *arm, const char *name);
+
+void ED_armature_edit_bone_remove_ex(struct bArmature *arm, EditBone *exBone, bool clear_connected);
void ED_armature_edit_bone_remove(struct bArmature *arm, EditBone *exBone);
bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child);
@@ -168,7 +170,7 @@ void ED_armature_ebone_from_mat3(EditBone *ebone, float mat[3][3]);
void ED_armature_ebone_from_mat4(EditBone *ebone, float mat[4][4]);
void transform_armature_mirror_update(struct Object *obedit);
-void ED_armature_origin_set(struct Scene *scene, struct Object *ob, float cursor[3], int centermode, int around);
+void ED_armature_origin_set(struct Object *ob, 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_apply_transform(struct Object *ob, float mat[4][4], const bool do_props);
@@ -185,9 +187,7 @@ void create_vgroups_from_armature(
/* if bone is already in list, pass it as param to ignore it */
void unique_editbone_name(struct ListBase *ebones, char *name, EditBone *bone);
void ED_armature_bone_rename(struct bArmature *arm, const char *oldnamep, const char *newnamep);
-void ED_armature_bones_flip_names(struct bArmature *arm, struct ListBase *bones_names);
-
-void undo_push_armature(struct bContext *C, const char *name);
+void ED_armature_bones_flip_names(struct bArmature *arm, struct ListBase *bones_names, const bool do_strip_numbers);
/* low level selection functions which handle */
int ED_armature_ebone_selectflag_get(const EditBone *ebone);
@@ -196,9 +196,19 @@ void ED_armature_ebone_select_set(EditBone *ebone, bool select);
void ED_armature_ebone_selectflag_enable(EditBone *ebone, int flag);
void ED_armature_ebone_selectflag_disable(EditBone *ebone, int flag);
+/* editarmature_undo.c */
+void ED_armature_undosys_type(struct UndoType *ut);
+
+/* armature_utils.c */
+void ED_armature_ebone_listbase_temp_clear(struct ListBase *lb);
+void ED_armature_ebone_listbase_free(struct ListBase *lb);
+void ED_armature_ebone_listbase_copy(struct ListBase *lb_dst, struct ListBase *lb_src);
+
/* poseobject.c */
-void ED_armature_exit_posemode(struct bContext *C, struct Base *base);
-void ED_armature_enter_posemode(struct bContext *C, struct Base *base);
+bool ED_object_posemode_exit_ex(struct Main *bmain, struct Object *ob);
+bool ED_object_posemode_exit(struct bContext *C, struct Object *ob);
+bool ED_object_posemode_enter_ex(struct Main *bmain, struct Object *ob);
+bool ED_object_posemode_enter(struct bContext *C, struct Object *ob);
void ED_pose_de_selectall(struct Object *ob, int select_mode, const bool ignore_visibility);
void ED_pose_bone_select(struct Object *ob, struct bPoseChannel *pchan, bool select);
void ED_pose_recalculate_paths(struct bContext *C, struct Scene *scene, struct Object *ob);
diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h
index 859d45e9c86..da726cb8000 100644
--- a/source/blender/editors/include/ED_curve.h
+++ b/source/blender/editors/include/ED_curve.h
@@ -41,6 +41,7 @@ struct Curve;
struct EditNurb;
struct BezTriple;
struct BPoint;
+struct UndoType;
/* curve_ops.c */
void ED_operatortypes_curve(void);
@@ -48,8 +49,7 @@ void ED_operatormacros_curve(void);
void ED_keymap_curve(struct wmKeyConfig *keyconf);
/* editcurve.c */
-void undo_push_curve(struct bContext *C, const char *name);
-ListBase *object_editcurve_get(struct Object *ob);
+struct ListBase *object_editcurve_get(struct Object *ob);
void ED_curve_editnurb_load(struct Object *obedit);
void ED_curve_editnurb_make(struct Object *obedit);
@@ -72,6 +72,9 @@ void ED_curve_deselect_all(struct EditNurb *editnurb);
void ED_curve_select_all(struct EditNurb *editnurb);
void ED_curve_select_swap(struct EditNurb *editnurb, bool hide_handles);
+/* editcurve_undo.c */
+void ED_curve_undosys_type(struct UndoType *ut);
+
/* editfont.c */
void ED_curve_editfont_load(struct Object *obedit);
void ED_curve_editfont_make(struct Object *obedit);
@@ -89,7 +92,8 @@ bool ED_curve_active_center(struct Curve *cu, float center[3]);
bool ED_curve_editfont_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
/* editfont_undo.c */
-void undo_push_font(struct bContext *C, const char *name);
+void ED_font_undosys_type(struct UndoType *ut);
+
#if 0
/* debug only */
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index 95ba6095517..cb824b3c9b7 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -75,7 +75,7 @@ bool ED_space_image_show_uvedit(struct SpaceImage *sima, struct Object *obedit);
bool ED_space_image_paint_curve(const struct bContext *C);
-bool ED_space_image_check_show_maskedit(struct ViewLayer *view_layer, struct SpaceImage *sima);
+bool ED_space_image_check_show_maskedit(struct SpaceImage *sima, struct ViewLayer *view_layer);
int ED_space_image_maskedit_poll(struct bContext *C);
int ED_space_image_maskedit_mask_poll(struct bContext *C);
diff --git a/source/blender/editors/include/ED_lattice.h b/source/blender/editors/include/ED_lattice.h
index 30d66577770..b30929f5307 100644
--- a/source/blender/editors/include/ED_lattice.h
+++ b/source/blender/editors/include/ED_lattice.h
@@ -4,7 +4,7 @@
* 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.
+ * 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
@@ -18,7 +18,6 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -31,10 +30,19 @@
#ifndef __ED_LATTICE_H__
#define __ED_LATTICE_H__
+struct wmKeyConfig;
+struct UndoType;
struct Object;
-void ED_lattice_editlatt_free(struct Object *ob);
-void ED_lattice_editlatt_make(struct Object *obedit);
-void ED_lattice_editlatt_load(struct Object *obedit);
+/* lattice_ops.c */
+void ED_operatortypes_lattice(void);
+void ED_keymap_lattice(struct wmKeyConfig *keyconf);
+
+/* editlattice_select.c */
+void ED_lattice_flags_set(struct Object *obedit, int flag);
+bool ED_lattice_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
+
+/* editlattice_undo.c */
+void ED_lattice_undosys_type(struct UndoType *ut);
#endif /* __ED_LATTICE_H__ */
diff --git a/source/blender/editors/include/ED_mball.h b/source/blender/editors/include/ED_mball.h
index 232d7d1d234..9982c87a764 100644
--- a/source/blender/editors/include/ED_mball.h
+++ b/source/blender/editors/include/ED_mball.h
@@ -34,6 +34,7 @@
struct bContext;
struct Object;
struct wmKeyConfig;
+struct UndoType;
void ED_operatortypes_metaball(void);
void ED_operatormacros_metaball(void);
@@ -47,6 +48,7 @@ void ED_mball_editmball_free(struct Object *obedit);
void ED_mball_editmball_make(struct Object *obedit);
void ED_mball_editmball_load(struct Object *obedit);
-void undo_push_mball(struct bContext *C, const char *name);
+/* editmball_undo.c */
+void ED_mball_undosys_type(struct UndoType *ut);
#endif /* __ED_MBALL_H__ */
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 78497b29313..3217433204e 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -36,7 +36,6 @@ extern "C" {
#endif
struct ID;
-struct EvaluationContext;
struct View3D;
struct ARegion;
struct bContext;
@@ -63,6 +62,7 @@ struct UvMapVert;
struct ToolSettings;
struct Object;
struct rcti;
+struct UndoType;
/* editmesh_utils.c */
void EDBM_verts_mirror_cache_begin_ex(struct BMEditMesh *em, const int axis,
@@ -81,7 +81,7 @@ void EDBM_mesh_normals_update(struct BMEditMesh *em);
void EDBM_mesh_clear(struct BMEditMesh *em);
void EDBM_selectmode_to_scene(struct bContext *C);
-void EDBM_mesh_make(struct ToolSettings *ts, struct Object *ob, const bool add_key_index);
+void EDBM_mesh_make(struct Object *ob, const int select_mode, const bool add_key_index);
void EDBM_mesh_free(struct BMEditMesh *em);
void EDBM_mesh_load(struct Object *ob);
struct DerivedMesh *EDBM_mesh_deform_dm_get(struct BMEditMesh *em);
@@ -99,8 +99,6 @@ void EDBM_selectmode_flush(struct BMEditMesh *em);
void EDBM_deselect_flush(struct BMEditMesh *em);
void EDBM_select_flush(struct BMEditMesh *em);
-void undo_push_mesh(struct bContext *C, const char *name);
-
bool EDBM_vert_color_check(struct BMEditMesh *em);
void EDBM_mesh_hide(struct BMEditMesh *em, bool swap);
@@ -115,7 +113,8 @@ void BM_uv_element_map_free(struct UvElementMap *vmap);
struct UvElement *BM_uv_element_get(struct UvElementMap *map, struct BMFace *efa, struct BMLoop *l);
bool EDBM_uv_check(struct BMEditMesh *em);
-struct BMFace *EDBM_uv_active_face_get(struct BMEditMesh *em, const bool sloppy, const bool selected);
+struct BMFace *EDBM_uv_active_face_get(
+ struct BMEditMesh *em, const bool sloppy, const bool selected);
void BM_uv_vert_map_free(struct UvVertMap *vmap);
struct UvMapVert *BM_uv_vert_map_at_index(struct UvVertMap *vmap, unsigned int v);
@@ -130,6 +129,9 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree, struct BMEdge *e,
const struct Depsgraph *depsgraph,
struct ARegion *ar, struct View3D *v3d, struct Object *obedit);
+/* 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,
@@ -219,12 +221,14 @@ typedef struct MirrTopoStore_t {
intptr_t *index_lookup;
int prev_vert_tot;
int prev_edge_tot;
- int prev_ob_mode;
+ bool prev_is_editmode;
} MirrTopoStore_t;
-bool ED_mesh_mirrtopo_recalc_check(struct Mesh *me, struct DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store);
-void ED_mesh_mirrtopo_init(struct Mesh *me, struct DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
- const bool skip_em_vert_array_init);
+bool ED_mesh_mirrtopo_recalc_check(
+ struct Mesh *me, struct DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store);
+void ED_mesh_mirrtopo_init(
+ struct Mesh *me, struct DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store,
+ const bool skip_em_vert_array_init);
void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 8d2ff327c51..83119062203 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -52,9 +52,14 @@ struct wmKeyConfig;
struct wmKeyMap;
struct wmOperator;
struct wmOperatorType;
+struct wmWindow;
+struct wmWindowManager;
struct PointerRNA;
struct PropertyRNA;
struct EnumPropertyItem;
+struct EvaluationContext;
+
+#include "DNA_object_enums.h"
/* object_edit.c */
struct Object *ED_object_context(struct bContext *C); /* context.object */
@@ -113,21 +118,46 @@ struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, st
void ED_object_parent(struct Object *ob, struct Object *parent, const int type, const char *substr);
-bool ED_object_mode_compat_set(struct bContext *C, struct Object *ob, int mode, struct ReportList *reports);
-void ED_object_toggle_modes(struct bContext *C, int mode);
-
/* bitflags for enter/exit editmode */
-#define EM_FREEDATA 1
-#define EM_FREEUNDO 2
-#define EM_WAITCURSOR 4
-#define EM_DO_UNDO 8
-#define EM_IGNORE_LAYER 16
+enum {
+ EM_FREEDATA = (1 << 0),
+ EM_WAITCURSOR = (1 << 1),
+ EM_DO_UNDO = (1 << 2),
+ EM_IGNORE_LAYER = (1 << 3),
+};
+void ED_object_editmode_exit_ex(
+ struct bContext *C, struct Scene *scene, struct Object *obedit, int flag);
void ED_object_editmode_exit(struct bContext *C, int flag);
void ED_object_editmode_enter(struct bContext *C, int flag);
bool ED_object_editmode_load(struct Object *obedit);
bool ED_object_editmode_calc_active_center(struct Object *obedit, const bool select_only, float r_center[3]);
+
+void ED_object_vpaintmode_enter_ex(
+ const struct EvaluationContext *eval_ctx, struct wmWindowManager *wm,
+ struct Scene *scene, struct Object *ob);
+void ED_object_vpaintmode_enter(struct bContext *C);
+void ED_object_wpaintmode_enter_ex(
+ const struct EvaluationContext *eval_ctx, struct wmWindowManager *wm,
+ struct Scene *scene, struct Object *ob);
+void ED_object_wpaintmode_enter(struct bContext *C);
+
+void ED_object_vpaintmode_exit_ex(struct Object *ob);
+void ED_object_vpaintmode_exit(struct bContext *C);
+void ED_object_wpaintmode_exit_ex(struct Object *ob);
+void ED_object_wpaintmode_exit(struct bContext *C);
+
+void ED_object_sculptmode_enter_ex(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene, struct Object *ob,
+ struct ReportList *reports);
+void ED_object_sculptmode_enter(struct bContext *C, struct ReportList *reports);
+void ED_object_sculptmode_exit_ex(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene, struct Object *ob);
+void ED_object_sculptmode_exit(struct bContext *C);
+
void ED_object_location_from_view(struct bContext *C, float loc[3]);
void ED_object_rotation_from_view(struct bContext *C, float rot[3], const char align_axis);
void ED_object_base_init_transform(struct bContext *C, struct Base *base, const float loc[3], const float rot[3]);
@@ -173,13 +203,25 @@ void ED_object_constraint_dependency_update(struct Main *bmain, struct Object *o
void ED_object_constraint_tag_update(struct Object *ob, struct bConstraint *con);
void ED_object_constraint_dependency_tag_update(struct Main *bmain, struct Object *ob, struct bConstraint *con);
-/* object_lattice.c */
-bool ED_lattice_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
-void undo_push_lattice(struct bContext *C, const char *name);
+/* object_modes.c */
+bool ED_object_mode_compat_test(const struct Object *ob, eObjectMode mode);
+bool ED_object_mode_compat_set(struct bContext *C, struct Object *ob, eObjectMode mode, struct ReportList *reports);
+void ED_object_mode_toggle(struct bContext *C, eObjectMode mode);
+void ED_object_mode_set(struct bContext *C, eObjectMode mode);
-/* object_lattice.c */
-
-void ED_lattice_flags_set(struct Object *obedit, int flag);
+bool ED_object_mode_generic_enter(
+ struct bContext *C,
+ eObjectMode object_mode);
+void ED_object_mode_generic_exit(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene, struct Object *ob);
+bool ED_object_mode_generic_has_data(
+ const struct EvaluationContext *eval_ctx,
+ struct Object *ob);
+
+bool ED_object_mode_generic_exists(
+ struct wmWindowManager *wm, struct Object *ob,
+ eObjectMode object_mode);
/* object_modifier.c */
enum {
@@ -196,13 +238,14 @@ int ED_object_modifier_move_down(struct ReportList *reports, struct Object *ob,
int ED_object_modifier_move_up(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
int ED_object_modifier_convert(struct ReportList *reports, struct Main *bmain, struct Scene *scene,
struct ViewLayer *view_layer, struct Object *ob, struct ModifierData *md);
-int ED_object_modifier_apply(struct ReportList *reports, const struct bContext *C, struct Scene *scene,
+int ED_object_modifier_apply(struct ReportList *reports, const struct EvaluationContext *eval_ctx, struct Scene *scene,
struct Object *ob, struct ModifierData *md, int mode);
int ED_object_modifier_copy(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
-bool ED_object_iter_other(struct Main *bmain, struct Object *orig_ob, const bool include_orig,
- bool (*callback)(struct Object *ob, void *callback_data),
- void *callback_data);
+bool ED_object_iter_other(
+ struct Main *bmain, struct Object *orig_ob, const bool include_orig,
+ bool (*callback)(struct Object *ob, void *callback_data),
+ void *callback_data);
bool ED_object_multires_update_totlevels_cb(struct Object *ob, void *totlevel_v);
diff --git a/source/blender/editors/include/ED_paint.h b/source/blender/editors/include/ED_paint.h
index e46f4b966c0..246419d64aa 100644
--- a/source/blender/editors/include/ED_paint.h
+++ b/source/blender/editors/include/ED_paint.h
@@ -28,37 +28,32 @@
struct bContext;
struct wmKeyConfig;
struct wmOperator;
+struct ImBuf;
+struct Image;
+struct UndoStep;
+struct UndoType;
/* paint_ops.c */
void ED_operatortypes_paint(void);
void ED_operatormacros_paint(void);
void ED_keymap_paint(struct wmKeyConfig *keyconf);
-/* paint_undo.c */
-enum {
- UNDO_PAINT_IMAGE = 0,
- UNDO_PAINT_MESH = 1,
-};
-
-typedef void (*UndoRestoreCb)(struct bContext *C, struct ListBase *lb);
-typedef void (*UndoFreeCb)(struct ListBase *lb);
-typedef bool (*UndoCleanupCb)(struct bContext *C, struct ListBase *lb);
-
-int ED_undo_paint_step(struct bContext *C, int type, int step, const char *name);
-void ED_undo_paint_step_num(struct bContext *C, int type, int num);
-const char *ED_undo_paint_get_name(struct bContext *C, int type, int nr, bool *r_active);
-void ED_undo_paint_free(void);
-bool ED_undo_paint_is_valid(int type, const char *name);
-bool ED_undo_paint_empty(int type);
-void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free, UndoCleanupCb cleanup);
-void ED_undo_paint_push_end(int type);
-
/* paint_image.c */
-/* image painting specific undo */
-void ED_image_undo_restore(struct bContext *C, struct ListBase *lb);
-void ED_image_undo_free(struct ListBase *lb);
void ED_imapaint_clear_partial_redraw(void);
void ED_imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h, bool find_old);
void ED_imapaint_bucket_fill(struct bContext *C, float color[3], struct wmOperator *op);
+/* paint_image_undo.c */
+void ED_image_undo_push_begin(const char *name);
+void ED_image_undo_push_end(void);
+void ED_image_undo_restore(struct UndoStep *us);
+
+void ED_image_undosys_type(struct UndoType *ut);
+
+/* paint_curve_undo.c */
+void ED_paintcurve_undo_push_begin(const char *name);
+void ED_paintcurve_undo_push_end(void);
+
+void ED_paintcurve_undosys_type(struct UndoType *ut);
+
#endif /* __ED_PAINT_H__ */
diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h
index ffa6db18caa..b3e274a235a 100644
--- a/source/blender/editors/include/ED_particle.h
+++ b/source/blender/editors/include/ED_particle.h
@@ -39,13 +39,14 @@ struct rcti;
struct PTCacheEdit;
struct Scene;
struct ViewLayer;
+struct UndoType;
/* particle edit mode */
void PE_free_ptcache_edit(struct PTCacheEdit *edit);
int PE_start_edit(struct PTCacheEdit *edit);
/* access */
-struct PTCacheEdit *PE_get_current(struct Scene *scene, struct ViewLayer *view_layer, struct Object *ob);
+struct PTCacheEdit *PE_get_current(struct Scene *scene, struct Object *ob);
struct PTCacheEdit *PE_create_current(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
void PE_current_changed(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
int PE_minmax(struct Scene *scene, struct ViewLayer *view_layer, float min[3], float max[3]);
@@ -55,7 +56,7 @@ struct ParticleEditSettings *PE_settings(struct Scene *scene);
void PE_hide_keys_time(struct Scene *scene, struct PTCacheEdit *edit, float cfra);
void PE_update_object(
const struct EvaluationContext *eval_ctx, struct Scene *scene,
- struct ViewLayer *view_layer, struct Object *ob, int useflag);
+ struct Object *ob, int useflag);
/* selection tools */
int PE_mouse_particles(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
@@ -64,14 +65,8 @@ int PE_circle_select(struct bContext *C, int selecting, const int mval[2], float
int PE_lasso_select(struct bContext *C, const int mcords[][2], const short moves, bool extend, bool select);
void PE_deselect_all_visible(struct PTCacheEdit *edit);
-/* undo */
-void PE_undo_push(struct Scene *scene, struct ViewLayer *view_layer, const char *str);
-void PE_undo_step(struct Scene *scene, struct ViewLayer *view_layer, int step);
-void PE_undo(struct Scene *scene, struct ViewLayer *view_layer);
-void PE_redo(struct Scene *scene, struct ViewLayer *view_layer);
-bool PE_undo_is_valid(struct Scene *scene, struct ViewLayer *view_layer);
-void PE_undo_number(struct Scene *scene, struct ViewLayer *view_layer, int nr);
-const char *PE_undo_get_name(struct Scene *scene, struct ViewLayer *view_layer, int nr, bool *r_active);
+/* particle_edit_undo.c */
+void ED_particle_undosys_type(struct UndoType *ut);
#endif /* __ED_PARTICLE_H__ */
diff --git a/source/blender/editors/include/ED_scene.h b/source/blender/editors/include/ED_scene.h
index 647a8dda1b9..9b48187e541 100644
--- a/source/blender/editors/include/ED_scene.h
+++ b/source/blender/editors/include/ED_scene.h
@@ -31,9 +31,10 @@ enum eSceneCopyMethod;
struct Scene *ED_scene_add(struct Main *bmain, struct bContext *C, struct wmWindow *win, enum eSceneCopyMethod method) ATTR_NONNULL();
bool ED_scene_delete(struct bContext *C, struct Main *bmain, struct wmWindow *win, struct Scene *scene) ATTR_NONNULL();
-void ED_scene_exit(struct bContext *C) ATTR_NONNULL();
-void ED_scene_changed_update(struct Main *bmain, struct bContext *C, struct Scene *scene_new,
- const struct bScreen *active_screen) ATTR_NONNULL();
+void ED_scene_change_update(
+ struct Main *bmain, struct bContext *C,
+ struct wmWindow *win, const struct bScreen *screen,
+ struct Scene *scene_old, struct Scene *scene_new) ATTR_NONNULL();
bool ED_scene_view_layer_delete(
struct Main *bmain, struct Scene *scene, struct ViewLayer *layer,
struct ReportList *reports) ATTR_NONNULL(1, 2, 3);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index fdf22cd0f53..ea8a7c217a2 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -37,6 +37,8 @@
#include "DNA_view3d_types.h"
#include "DNA_workspace_types.h"
+#include "DNA_object_enums.h"
+
#include "BLI_compiler_attrs.h"
struct Depsgraph;
@@ -66,7 +68,6 @@ void ED_region_do_listen(
void ED_region_do_draw(struct bContext *C, struct ARegion *ar);
void ED_region_exit(struct bContext *C, struct ARegion *ar);
void ED_region_pixelspace(struct ARegion *ar);
-void ED_region_set(const struct bContext *C, struct ARegion *ar);
void ED_region_update_rect(struct bContext *C, struct ARegion *ar);
void ED_region_init(struct bContext *C, struct ARegion *ar);
void ED_region_tag_redraw(struct ARegion *ar);
@@ -135,7 +136,7 @@ void ED_screen_update_after_scene_change(
const struct bScreen *screen,
struct Scene *scene_new,
struct ViewLayer *view_layer);
-void ED_screen_set_subwinactive(struct bContext *C, const struct wmEvent *event);
+void ED_screen_set_active_region(struct bContext *C, const struct wmEvent *event);
void ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen);
void ED_screen_animation_timer(struct bContext *C, int redraws, int refresh, int sync, int enable);
void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh);
@@ -147,6 +148,8 @@ struct ScrArea *ED_screen_state_toggle(struct bContext *C, struct wmWindow *win,
void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
bool ED_screen_stereo3d_required(const struct bScreen *screen, const struct Scene *scene);
Scene *ED_screen_scene_find(const struct bScreen *screen, const struct wmWindowManager *wm);
+Scene *ED_screen_scene_find_with_window(const struct bScreen *screen, const struct wmWindowManager *wm, struct wmWindow **r_window);
+struct wmWindow *ED_screen_window_find(const struct bScreen *screen, const struct wmWindowManager *wm);
void ED_screen_preview_render(const struct bScreen *screen, int size_x, int size_y, unsigned int *r_rect) ATTR_NONNULL();
/* workspaces */
@@ -186,8 +189,13 @@ bool ED_workspace_layout_cycle(
struct WorkSpace *workspace, const short direction,
struct bContext *C) ATTR_NONNULL();
+void ED_workspace_object_mode_sync_from_object(
+ struct wmWindowManager *wm, WorkSpace *workspace, struct Object *obact);
+void ED_workspace_object_mode_sync_from_scene(
+ struct wmWindowManager *wm, WorkSpace *workspace, struct Scene *scene);
+
/* anim */
-void ED_update_for_newframe(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct Depsgraph *depsgraph);
+void ED_update_for_newframe(struct Main *bmain, struct Depsgraph *depsgraph);
void ED_refresh_viewport_fps(struct bContext *C);
int ED_screen_animation_play(struct bContext *C, int sync, int mode);
diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h
index a81d63d9f25..574523696f5 100644
--- a/source/blender/editors/include/ED_sculpt.h
+++ b/source/blender/editors/include/ED_sculpt.h
@@ -36,10 +36,16 @@ struct Object;
struct RegionView3D;
struct ViewContext;
struct rcti;
+struct UndoStep;
+struct UndoType;
+struct ListBase;
/* sculpt.c */
void ED_operatortypes_sculpt(void);
void ED_sculpt_redraw_planes_get(float planes[4][4], struct ARegion *ar, struct Object *ob);
int ED_sculpt_mask_box_select(struct bContext *C, struct ViewContext *vc, const struct rcti *rect, bool select, bool extend);
+/* sculpt_undo.c */
+void ED_sculpt_undosys_type(struct UndoType *ut);
+
#endif /* __ED_SCULPT_H__ */
diff --git a/source/blender/editors/include/ED_text.h b/source/blender/editors/include/ED_text.h
index 5df7d9cfaef..763fbe3bac5 100644
--- a/source/blender/editors/include/ED_text.h
+++ b/source/blender/editors/include/ED_text.h
@@ -30,12 +30,16 @@
#ifndef __ED_TEXT_H__
#define __ED_TEXT_H__
-struct bContext;
struct SpaceText;
struct ARegion;
+struct UndoType;
+struct TextUndoBuf;
-void ED_text_undo_step(struct bContext *C, int step);
bool ED_text_region_location_from_cursor(struct SpaceText *st, struct ARegion *ar, const int cursor_co[2], int r_pixel_co[2]);
-#endif /* __ED_TEXT_H__ */
+/* text_undo.c */
+void ED_text_undosys_type(struct UndoType *ut);
+
+struct TextUndoBuf *ED_text_undo_push_init(struct bContext *C);
+#endif /* __ED_TEXT_H__ */
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 8761f2c5361..26cef2599bd 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -30,7 +30,6 @@ struct BMEdge;
struct BMFace;
struct ListBase;
-struct RenderEngineType;
struct Scene;
struct ViewLayer;
struct Main;
@@ -76,9 +75,9 @@ struct SnapObjectParams {
typedef struct SnapObjectContext SnapObjectContext;
SnapObjectContext *ED_transform_snap_object_context_create(
- struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct RenderEngineType *engine_type, int flag);
+ struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, int flag);
SnapObjectContext *ED_transform_snap_object_context_create_view3d(
- struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct RenderEngineType *engine_type, int flag,
+ struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, int flag,
/* extra args for view3d */
const struct ARegion *ar, const struct View3D *v3d);
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx);
diff --git a/source/blender/editors/include/ED_undo.h b/source/blender/editors/include/ED_undo.h
new file mode 100644
index 00000000000..b3814ab5899
--- /dev/null
+++ b/source/blender/editors/include/ED_undo.h
@@ -0,0 +1,64 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ED_undo.h
+ * \ingroup editors
+ */
+
+#ifndef __ED_UNDO_H__
+#define __ED_UNDO_H__
+
+struct bContext;
+struct wmOperator;
+struct wmOperatorType;
+struct UndoStack;
+
+/* undo.c */
+void ED_undo_push(struct bContext *C, const char *str);
+void ED_undo_push_op(struct bContext *C, struct wmOperator *op);
+void ED_undo_grouped_push(struct bContext *C, const char *str);
+void ED_undo_grouped_push_op(struct bContext *C, struct wmOperator *op);
+void ED_undo_pop_op(struct bContext *C, struct wmOperator *op);
+void ED_undo_pop(struct bContext *C);
+void ED_undo_redo(struct bContext *C);
+void ED_OT_undo(struct wmOperatorType *ot);
+void ED_OT_undo_push(struct wmOperatorType *ot);
+void ED_OT_redo(struct wmOperatorType *ot);
+void ED_OT_undo_redo(struct wmOperatorType *ot);
+void ED_OT_undo_history(struct wmOperatorType *ot);
+
+int ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op);
+/* convenience since UI callbacks use this mostly*/
+void ED_undo_operator_repeat_cb(struct bContext *C, void *arg_op, void *arg_unused);
+void ED_undo_operator_repeat_cb_evt(struct bContext *C, void *arg_op, int arg_unused);
+
+bool ED_undo_is_valid(const struct bContext *C, const char *undoname);
+
+struct UndoStack *ED_undo_stack_get(void);
+
+/* undo_system_types.c */
+void ED_undosys_type_init(void);
+void ED_undosys_type_free(void);
+
+/* memfile_undo.c */
+struct MemFile *ED_undosys_stack_memfile_get_active(struct UndoStack *ustack);
+
+#endif /* __ED_UNDO_H__ */
+
diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h
index 60c4b3593aa..2653585dacc 100644
--- a/source/blender/editors/include/ED_util.h
+++ b/source/blender/editors/include/ED_util.h
@@ -32,9 +32,10 @@
#define __ED_UTIL_H__
struct bContext;
-struct SpaceLink;
-struct wmOperator;
struct wmOperatorType;
+struct ScrArea;
+struct SpaceLink;
+struct PackedFile;
/* ed_util.c */
@@ -47,40 +48,6 @@ void ED_spacedata_id_remap(struct ScrArea *sa, struct SpaceLink *sl, struct I
void ED_OT_flush_edits(struct wmOperatorType *ot);
-/* ************** Undo ************************ */
-
-/* undo.c */
-void ED_undo_push(struct bContext *C, const char *str);
-void ED_undo_push_op(struct bContext *C, struct wmOperator *op);
-void ED_undo_grouped_push(struct bContext *C, const char *str);
-void ED_undo_grouped_push_op(struct bContext *C, struct wmOperator *op);
-void ED_undo_pop_op(struct bContext *C, struct wmOperator *op);
-void ED_undo_pop(struct bContext *C);
-void ED_undo_redo(struct bContext *C);
-void ED_OT_undo(struct wmOperatorType *ot);
-void ED_OT_undo_push(struct wmOperatorType *ot);
-void ED_OT_redo(struct wmOperatorType *ot);
-void ED_OT_undo_redo(struct wmOperatorType *ot);
-void ED_OT_undo_history(struct wmOperatorType *ot);
-
-int ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op);
-/* convenience since UI callbacks use this mostly*/
-void ED_undo_operator_repeat_cb(struct bContext *C, void *arg_op, void *arg_unused);
-void ED_undo_operator_repeat_cb_evt(struct bContext *C, void *arg_op, int arg_unused);
-
-bool ED_undo_is_valid(const struct bContext *C, const char *undoname);
-
-/* undo_editmode.c */
-void undo_editmode_push(struct bContext *C, const char *name,
- void * (*getdata)(struct bContext *C),
- void (*freedata)(void *),
- void (*to_editmode)(void *, void *, void *),
- void *(*from_editmode)(void *, void *),
- int (*validate_undo)(void *, void *));
-
-
-void undo_editmode_clear(void);
-
/* ************** XXX OLD CRUFT WARNING ************* */
void apply_keyb_grid(int shift, int ctrl, float *val, float fac1, float fac2, float fac3, int invert);
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index 96b4004b6a6..2a5ad494643 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -50,49 +50,65 @@ struct wmKeyConfig;
void ED_operatortypes_uvedit(void);
void ED_keymap_uvedit(struct wmKeyConfig *keyconf);
-void ED_uvedit_assign_image(struct Main *bmain, struct Scene *scene, struct Object *obedit, struct Image *ima, struct Image *previma);
+void ED_uvedit_assign_image(
+ struct Main *bmain, struct Scene *scene, struct Object *obedit, struct Image *ima, struct Image *previma);
bool ED_uvedit_minmax(struct Scene *scene, struct Image *ima, struct Object *obedit, float min[2], float max[2]);
bool ED_uvedit_center(Scene *scene, Image *ima, struct Object *obedit, float cent[2], char mode);
void ED_uvedit_select_all(struct BMesh *bm);
-bool ED_object_get_active_image(struct Object *ob, int mat_nr,
- struct Image **r_ima, struct ImageUser **r_iuser, struct bNode **r_node, struct bNodeTree **r_ntree);
+bool ED_object_get_active_image(
+ struct Object *ob, int mat_nr,
+ struct Image **r_ima, struct ImageUser **r_iuser, struct bNode **r_node, struct bNodeTree **r_ntree);
void ED_object_assign_active_image(struct Main *bmain, struct Object *ob, int mat_nr, struct Image *ima);
bool ED_uvedit_test(struct Object *obedit);
/* visibility and selection */
-bool uvedit_face_visible_test(struct Scene *scene, struct Image *ima, struct BMFace *efa);
-bool uvedit_face_select_test(struct Scene *scene, struct BMFace *efa,
- const int cd_loop_uv_offset);
-bool uvedit_edge_select_test(struct Scene *scene, struct BMLoop *l,
- const int cd_loop_uv_offset);
-bool uvedit_uv_select_test(struct Scene *scene, struct BMLoop *l,
- const int cd_loop_uv_offset);
+bool uvedit_face_visible_test(
+ struct Scene *scene, struct Object *obedit, struct Image *ima, struct BMFace *efa);
+bool uvedit_face_select_test(
+ struct Scene *scene, struct BMFace *efa,
+ const int cd_loop_uv_offset);
+bool uvedit_edge_select_test(
+ struct Scene *scene, struct BMLoop *l,
+ const int cd_loop_uv_offset);
+bool uvedit_uv_select_test(
+ struct Scene *scene, struct BMLoop *l,
+ const int cd_loop_uv_offset);
/* uv face */
-bool uvedit_face_select_set(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa, const bool select,
- const bool do_history, const int cd_loop_uv_offset);
-bool uvedit_face_select_enable(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa,
- const bool do_history, const int cd_loop_uv_offset);
-bool uvedit_face_select_disable(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa,
- const int cd_loop_uv_offset);
+bool uvedit_face_select_set(
+ struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa, const bool select,
+ const bool do_history, const int cd_loop_uv_offset);
+bool uvedit_face_select_enable(
+ struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa,
+ const bool do_history, const int cd_loop_uv_offset);
+bool uvedit_face_select_disable(
+ struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa,
+ const int cd_loop_uv_offset);
/* uv edge */
-void uvedit_edge_select_set(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, const bool select,
- const bool do_history, const int cd_loop_uv_offset);
-void uvedit_edge_select_enable(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l,
- const bool do_history, const int cd_loop_uv_offset);
-void uvedit_edge_select_disable(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l,
- const int cd_loop_uv_offset);
+void uvedit_edge_select_set(
+ struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, const bool select,
+ const bool do_history, const int cd_loop_uv_offset);
+void uvedit_edge_select_enable(
+ struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l,
+ const bool do_history, const int cd_loop_uv_offset);
+void uvedit_edge_select_disable(
+ struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l,
+ const int cd_loop_uv_offset);
/* uv vert */
-void uvedit_uv_select_set(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, const bool select,
- const bool do_history, const int cd_loop_uv_offset);
-void uvedit_uv_select_enable(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l,
- const bool do_history, const int cd_loop_uv_offset);
-void uvedit_uv_select_disable(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l,
- const int cd_loop_uv_offset);
-
-bool ED_uvedit_nearest_uv(struct Scene *scene, struct Object *obedit, struct Image *ima,
- const float co[2], float r_uv[2]);
+void uvedit_uv_select_set(
+ struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, const bool select,
+ const bool do_history, const int cd_loop_uv_offset);
+void uvedit_uv_select_enable(
+ struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l,
+ const bool do_history, const int cd_loop_uv_offset);
+void uvedit_uv_select_disable(
+ struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l,
+ const int cd_loop_uv_offset);
+
+bool ED_uvedit_nearest_uv(
+ struct Scene *scene, struct Object *obedit, struct Image *ima,
+ const float co[2], float r_uv[2]);
void ED_uvedit_get_aspect(struct Scene *scene, struct Object *ob, struct BMesh *em, float *aspx, float *aspy);
@@ -102,7 +118,8 @@ void ED_uvedit_live_unwrap_re_solve(void);
void ED_uvedit_live_unwrap_end(short cancel);
void ED_uvedit_live_unwrap(struct Scene *scene, struct Object *obedit);
-void ED_uvedit_pack_islands(struct Scene *scene, struct Object *ob, struct BMesh *bm, bool selected, bool correct_aspect, bool do_rotate);
+void ED_uvedit_pack_islands(
+struct Scene *scene, struct Object *ob, struct BMesh *bm, bool selected, bool correct_aspect, bool do_rotate);
void ED_uvedit_unwrap_cube_project(
struct BMesh *bm, float cube_size, bool use_select, const float center[3]);
@@ -111,8 +128,12 @@ void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel)
/* uvedit_draw.c */
-void ED_image_draw_cursor(struct ARegion *ar, const float cursor[2]);
-void ED_uvedit_draw_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct ViewLayer *view_layer, struct Object *obedit, struct Object *obact, struct Depsgraph *depsgraph);
+void ED_image_draw_cursor(
+struct ARegion *ar, const float cursor[2]);
+void ED_uvedit_draw_main(
+ struct SpaceImage *sima,
+ struct ARegion *ar, struct Scene *scene, struct ViewLayer *view_layer,
+ struct Object *obedit, struct Object *obact, struct Depsgraph *depsgraph);
/* uvedit_buttons.c */
void ED_uvedit_buttons_register(struct ARegionType *art);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 8201401296a..1d4fc8891f5 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -363,7 +363,7 @@ int view3d_opengl_select(
/* view3d_select.c */
float ED_view3d_select_dist_px(void);
-void view3d_set_viewcontext(struct bContext *C, struct ViewContext *vc);
+void ED_view3d_viewcontext_init(struct bContext *C, struct ViewContext *vc);
void view3d_operator_needs_opengl(const struct bContext *C);
void view3d_region_operator_needs_opengl(struct wmWindow *win, struct ARegion *ar);
void view3d_opengl_read_pixels(struct ARegion *ar, int x, int y, int w, int h, int format, int type, void *data);
@@ -395,12 +395,14 @@ void ED_draw_object_facemap(const struct EvaluationContext *eval_ctx, struct Sc
bool ED_view3d_context_activate(struct bContext *C);
void ED_view3d_draw_offscreen_init(
const struct EvaluationContext *eval_ctx, struct Scene *scene,
- struct ViewLayer *view_layer, struct View3D *v3d);
+ struct ViewLayer *view_layer, struct RenderEngineType *engine_type,
+ struct View3D *v3d);
void ED_view3d_draw_offscreen(
const struct EvaluationContext *eval_ctx, struct Scene *scene,
- struct ViewLayer *view_layer, struct View3D *v3d, struct ARegion *ar, int winx, int winy, float viewmat[4][4],
+ struct ViewLayer *view_layer, struct RenderEngineType *engine_type,
+ struct View3D *v3d, struct ARegion *ar, int winx, int winy, float viewmat[4][4],
float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp, const char *viewname,
- struct GPUFX *fx, struct GPUFXSettings *fx_settings,
+ struct GPUFXSettings *fx_settings,
struct GPUOffScreen *ofs, struct GPUViewport *viewport);
void ED_view3d_draw_setup_view(
struct wmWindow *win, const struct EvaluationContext *eval_ctx, struct Scene *scene, struct ARegion *ar, struct View3D *v3d,
@@ -420,16 +422,18 @@ enum {
struct ImBuf *ED_view3d_draw_offscreen_imbuf(
const struct EvaluationContext *eval_ctx, struct Scene *scene,
- struct ViewLayer *view_layer, struct View3D *v3d, struct ARegion *ar,
+ struct ViewLayer *view_layer, struct RenderEngineType *engine_type,
+ struct View3D *v3d, struct ARegion *ar,
int sizex, int sizey, unsigned int flag, unsigned int draw_flags,
int alpha_mode, int samples, const char *viewname,
- struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
+ struct GPUOffScreen *ofs, char err_out[256]);
struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
const struct EvaluationContext *eval_ctx, struct Scene *scene,
- struct ViewLayer *view_layer, struct Object *camera, int width, int height,
+ struct ViewLayer *view_layer, struct RenderEngineType *engine_type,
+ struct Object *camera, int width, int height,
unsigned int flag, unsigned int draw_flags, int drawtype, int alpha_mode,
int samples, const char *viewname,
- struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
+ struct GPUOffScreen *ofs, char err_out[256]);
struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip);
@@ -488,7 +492,7 @@ void ED_view3d_operator_properties_viewmat_get(struct wmOperator *op, int *winx,
/* render */
void ED_view3d_stop_render_preview(struct wmWindowManager *wm, struct ARegion *ar);
-void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View3D *v3d, struct ScrArea *sa);
+void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa);
#define V3D_IS_ZBUF(v3d) \
(((v3d)->flag & V3D_ZBUF_SELECT) && ((v3d)->drawtype > OB_WIRE))
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 6e09318314d..edf15d02e73 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -64,7 +64,6 @@ struct Image;
struct ImageUser;
struct wmKeyConfig;
struct wmOperatorType;
-struct uiWidgetColors;
struct MTex;
struct ImBuf;
struct bNodeTree;
@@ -1168,4 +1167,9 @@ void UI_tooltip_free(struct bContext *C, struct bScreen *sc, struct ARegion *ar)
int UI_calc_float_precision(int prec, double value);
+/* widget batched drawing */
+void UI_widgetbase_draw_cache_begin(void);
+void UI_widgetbase_draw_cache_flush(void);
+void UI_widgetbase_draw_cache_end(void);
+
#endif /* __UI_INTERFACE_H__ */
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index cee68ed361c..8b436942fdd 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -77,6 +77,9 @@ void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha);
void UI_icons_free(void);
void UI_icons_free_drawinfo(void *drawinfo);
+void UI_icon_draw_cache_begin(void);
+void UI_icon_draw_cache_end(void);
+
struct ListBase *UI_iconfile_list(void);
int UI_iconfile_get_index(const char *filename);
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index 94f377fb35e..c023816b52c 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -70,7 +70,9 @@ set(SRC
view2d.c
view2d_ops.c
+ interface_eyedropper_intern.h
interface_intern.h
+ interface_regions_intern.h
)
if(WITH_INTERNATIONAL)
@@ -81,6 +83,10 @@ if(WITH_HEADLESS)
add_definitions(-DWITH_HEADLESS)
endif()
+if(WITH_CYCLES)
+ add_definitions(-DWITH_CYCLES)
+endif()
+
if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 9e6d9f23442..12ee1ad35a1 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -64,12 +64,12 @@
#include "BLT_translation.h"
#include "UI_interface.h"
+#include "UI_interface_icons.h"
#include "IMB_imbuf.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "wm_subwindow.h"
#include "WM_message.h"
#include "RNA_access.h"
@@ -1222,11 +1222,9 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
void ui_but_override_flag(uiBut *but)
{
- bool is_overridden;
+ const int override_status = RNA_property_override_status(&but->rnapoin, but->rnaprop, but->rnaindex);
- RNA_property_override_status(&but->rnapoin, but->rnaprop, but->rnaindex, NULL, &is_overridden, NULL, NULL);
-
- if (is_overridden) {
+ if (override_status & RNA_OVERRIDE_STATUS_OVERRIDDEN) {
but->flag |= UI_BUT_OVERRIDEN;
}
else {
@@ -1393,7 +1391,6 @@ void UI_block_draw(const bContext *C, uiBlock *block)
ARegion *ar;
uiBut *but;
rcti rect;
- int multisample_enabled;
/* get menu region or area region */
ar = CTX_wm_menu(C);
@@ -1403,13 +1400,8 @@ void UI_block_draw(const bContext *C, uiBlock *block)
if (!block->endblock)
UI_block_end(C, block);
- /* disable AA, makes widgets too blurry */
- multisample_enabled = glIsEnabled(GL_MULTISAMPLE);
- if (multisample_enabled)
- glDisable(GL_MULTISAMPLE);
-
/* we set this only once */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
/* scale fonts */
ui_fontscale(&style.paneltitle.points, block->aspect);
@@ -1435,6 +1427,10 @@ void UI_block_draw(const bContext *C, uiBlock *block)
else if (block->panel)
ui_draw_aligned_panel(&style, block, &rect, UI_panel_category_is_visible(ar));
+ BLF_batch_draw_begin();
+ UI_icon_draw_cache_begin();
+ UI_widgetbase_draw_cache_begin();
+
/* widgets */
for (but = block->buttons.first; but; but = but->next) {
if (!(but->flag & (UI_HIDDEN | UI_SCROLLED))) {
@@ -1446,14 +1442,15 @@ void UI_block_draw(const bContext *C, uiBlock *block)
ui_draw_but(C, ar, &style, but, &rect);
}
}
+
+ UI_widgetbase_draw_cache_end();
+ UI_icon_draw_cache_end();
+ BLF_batch_draw_end();
/* restore matrix */
gpuPopProjectionMatrix();
gpuPopMatrix();
- if (multisample_enabled)
- glEnable(GL_MULTISAMPLE);
-
ui_draw_links(block);
}
@@ -2862,7 +2859,6 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, sh
uiBlock *block;
wmWindow *window;
Scene *scn;
- int getsizex, getsizey;
window = CTX_wm_window(C);
scn = CTX_data_scene(C);
@@ -2893,22 +2889,22 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, sh
UI_block_region_set(block, region);
/* window matrix and aspect */
- if (region && region->swinid) {
- wm_subwindow_matrix_get(window, region->swinid, block->winmat);
- wm_subwindow_size_get(window, region->swinid, &getsizex, &getsizey);
+ if (region && region->visible) {
+ gpuGetProjectionMatrix(block->winmat);
- block->aspect = 2.0f / fabsf(getsizex * block->winmat[0][0]);
+ block->aspect = 2.0f / fabsf(region->winx * block->winmat[0][0]);
}
else {
- const bScreen *screen = WM_window_get_active_screen(window);
-
/* no subwindow created yet, for menus for example, so we
* use the main window instead, since buttons are created
* there anyway */
- wm_subwindow_matrix_get(window, screen->mainwin, block->winmat);
- wm_subwindow_size_get(window, screen->mainwin, &getsizex, &getsizey);
+ int width = WM_window_pixels_x(window);
+ int height = WM_window_pixels_y(window);
+ rcti winrct = {0, width -1, 0, height - 1};
+
+ wmGetProjectionMatrix(block->winmat, &winrct);
- block->aspect = 2.0f / fabsf(getsizex * block->winmat[0][0]);
+ block->aspect = 2.0f / fabsf(width * block->winmat[0][0]);
block->auto_open = true;
block->flag |= UI_BLOCK_LOOP; /* tag as menu */
}
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 3ecb72353bc..f84347b97a4 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -64,6 +64,7 @@
/* own include */
#include "interface_intern.h"
+
static int roundboxtype = UI_CNR_ALL;
void UI_draw_roundbox_corner_set(int type)
@@ -101,12 +102,58 @@ void UI_draw_roundbox_3fvAlpha(bool filled, float minx, float miny, float maxx,
UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv);
}
+void UI_draw_roundbox_aa(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4])
+{
+ uiWidgetBaseParameters widget_params = {
+ .recti.xmin = minx, .recti.ymin = miny,
+ .recti.xmax = maxx, .recti.ymax = maxy,
+ .radi = rad,
+ .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
+ .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
+ .color_inner1[0] = color[0], .color_inner2[0] = color[0],
+ .color_inner1[1] = color[1], .color_inner2[1] = color[1],
+ .color_inner1[2] = color[2], .color_inner2[2] = color[2],
+ .color_inner1[3] = color[3], .color_inner2[3] = color[3],
+ };
+
+ glEnable(GL_BLEND);
+
+ if (filled) {
+ /* plain antialiased filled box */
+ widget_params.color_inner1[3] *= 0.125f;
+ widget_params.color_inner2[3] *= 0.125f;
+
+ /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space.
+ * If it has been scaled, then it's no longer valid. */
+ Gwn_Batch *batch = ui_batch_roundbox_get(filled, true);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
+ GWN_batch_draw(batch);
+ }
+ else {
+ /* plain antialiased unfilled box */
+ glEnable(GL_LINE_SMOOTH);
+
+ Gwn_Batch *batch = ui_batch_roundbox_get(filled, false);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
+ GWN_batch_draw(batch);
+
+ glDisable(GL_LINE_SMOOTH);
+ }
+
+ glDisable(GL_BLEND);
+}
+
void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[4])
{
+#if 0
float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
{0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
int a;
-
+
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -175,8 +222,29 @@ void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float
immEnd();
immUnbindProgram();
+#endif
+
+ uiWidgetBaseParameters widget_params = {
+ .recti.xmin = minx, .recti.ymin = miny,
+ .recti.xmax = maxx, .recti.ymax = maxy,
+ .radi = rad,
+ .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
+ .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
+ .color_inner1[0] = col[0], .color_inner2[0] = col[0],
+ .color_inner1[1] = col[1], .color_inner2[1] = col[1],
+ .color_inner1[2] = col[2], .color_inner2[2] = col[2],
+ .color_inner1[3] = col[3], .color_inner2[3] = col[3],
+ };
+
+ Gwn_Batch *batch = ui_batch_roundbox_get(filled, false);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
+ GWN_batch_draw(batch);
}
+#if 0
static void round_box_shade_col(unsigned attrib, const float col1[3], float const col2[3], const float fac)
{
float col[4] = {
@@ -187,6 +255,7 @@ static void round_box_shade_col(unsigned attrib, const float col1[3], float cons
};
immAttrib4fv(attrib, col);
}
+#endif
/* linear horizontal shade within button or in outline */
/* view2d scrollers use it */
@@ -194,6 +263,7 @@ void UI_draw_roundbox_shade_x(
bool filled, float minx, float miny, float maxx, float maxy,
float rad, float shadetop, float shadedown, const float col[4])
{
+#if 0
float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
{0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
const float div = maxy - miny;
@@ -305,6 +375,30 @@ void UI_draw_roundbox_shade_x(
immEnd();
immUnbindProgram();
+#endif
+
+ uiWidgetBaseParameters widget_params = {
+ .recti.xmin = minx, .recti.ymin = miny,
+ .recti.xmax = maxx, .recti.ymax = maxy,
+ .radi = rad,
+ .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
+ .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
+ .color_inner1[0] = min_ff(1.0f, col[0] + shadetop),
+ .color_inner2[0] = max_ff(0.0f, col[0] + shadedown),
+ .color_inner1[1] = min_ff(1.0f, col[1] + shadetop),
+ .color_inner2[1] = max_ff(0.0f, col[1] + shadedown),
+ .color_inner1[2] = min_ff(1.0f, col[2] + shadetop),
+ .color_inner2[2] = max_ff(0.0f, col[2] + shadedown),
+ .color_inner1[3] = 1.0f,
+ .color_inner2[3] = 1.0f,
+ };
+
+ Gwn_Batch *batch = ui_batch_roundbox_get(filled, false);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
+ GWN_batch_draw(batch);
}
#if 0 /* unused */
@@ -615,7 +709,7 @@ static void draw_scope_end(const rctf *rect, GLint *scissor)
/* restore scissortest */
glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
/* outline */
UI_draw_roundbox_corner_set(UI_CNR_ALL);
@@ -635,7 +729,7 @@ static void histogram_draw_one(
return;
glEnable(GL_LINE_SMOOTH);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
immUniformColor4fv(color);
@@ -665,7 +759,7 @@ static void histogram_draw_one(
/* curve outline */
immUniformColor4f(0.0f, 0.0f, 0.0f, 0.25f);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
immBegin(GWN_PRIM_LINE_STRIP, res);
for (int i = 0; i < res; i++) {
float x2 = x + i * (w / (float)res);
@@ -696,7 +790,7 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol)
float h = BLI_rctf_size_y(&rect) * hist->ymax;
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
float color[4];
UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
@@ -705,7 +799,7 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol)
/* need scissor test, histogram can draw outside of boundary */
GLint scissor[4];
- glGetIntegerv(GL_VIEWPORT, scissor);
+ glGetIntegerv(GL_SCISSOR_BOX, scissor);
glScissor(ar->winrct.xmin + (rect.xmin - 1),
ar->winrct.ymin + (rect.ymin - 1),
(rect.xmax + 1) - (rect.xmin - 1),
@@ -816,8 +910,11 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
}
}
+ /* Flush text cache before changing scissors. */
+ BLF_batch_draw_flush();
+
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
float color[4];
UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
@@ -825,7 +922,7 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
/* need scissor test, waveform can draw outside of boundary */
- glGetIntegerv(GL_VIEWPORT, scissor);
+ glGetIntegerv(GL_SCISSOR_BOX, scissor);
glScissor(ar->winrct.xmin + (rect.xmin - 1),
ar->winrct.ymin + (rect.ymin - 1),
(rect.xmax + 1) - (rect.xmin - 1),
@@ -840,8 +937,11 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
BLF_draw_default(rect.xmin + 1, yofs - 5 + (i * 0.2f) * h, 0, str, sizeof(str) - 1);
}
+ /* Flush text cache before drawing things on top. */
+ BLF_batch_draw_flush();
+
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -1085,7 +1185,7 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco
float alpha = scopes->vecscope_alpha * scopes->vecscope_alpha * scopes->vecscope_alpha;
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
float color[4];
UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
@@ -1094,7 +1194,7 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco
/* need scissor test, hvectorscope can draw outside of boundary */
GLint scissor[4];
- glGetIntegerv(GL_VIEWPORT, scissor);
+ glGetIntegerv(GL_SCISSOR_BOX, scissor);
glScissor(ar->winrct.xmin + (rect.xmin - 1),
ar->winrct.ymin + (rect.ymin - 1),
(rect.xmax + 1) - (rect.xmin - 1),
@@ -1520,7 +1620,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
/* need scissor test, curve can draw outside of boundary */
GLint scissor[4];
- glGetIntegerv(GL_VIEWPORT, scissor);
+ glGetIntegerv(GL_SCISSOR_BOX, scissor);
rcti scissor_new = {
.xmin = ar->winrct.xmin + rect->xmin,
.ymin = ar->winrct.ymin + rect->ymin,
@@ -1564,7 +1664,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
if (but->a1 == UI_GRAD_H) {
/* grid, hsv uses different grid */
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
immUniformColor4ub(0, 0, 0, 48);
ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.1666666f);
glDisable(GL_BLEND);
@@ -1738,11 +1838,11 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
int height = BLI_rctf_size_y(&rect);
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
/* need scissor test, preview image can draw outside of boundary */
GLint scissor[4];
- glGetIntegerv(GL_VIEWPORT, scissor);
+ glGetIntegerv(GL_SCISSOR_BOX, scissor);
glScissor(ar->winrct.xmin + (rect.xmin - 1),
ar->winrct.ymin + (rect.ymin - 1),
(rect.xmax + 1) - (rect.xmin - 1),
@@ -1874,7 +1974,7 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol
GLint scissor[4];
/* need scissor test, can draw outside of boundary */
- glGetIntegerv(GL_VIEWPORT, scissor);
+ glGetIntegerv(GL_SCISSOR_BOX, scissor);
rcti scissor_new = {
.xmin = ar->winrct.xmin + recti->xmin,
@@ -2031,16 +2131,40 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha
}
glEnable(GL_BLEND);
-
const float dalpha = alpha * 2.0f / 255.0f;
float calpha = dalpha;
- for (; i--; a -= aspect) {
+ float visibility = 1.0f;
+ for (; i--;) {
/* alpha ranges from 2 to 20 or so */
+#if 0 /* Old Method (pre 2.8) */
float color[4] = {0.0f, 0.0f, 0.0f, calpha};
UI_draw_roundbox_4fv(true, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color);
+#endif
+ /* Compute final visibility to match old method result. */
+ /* TODO we could just find a better fit function inside the shader instead of this. */
+ visibility = visibility * (1.0f - calpha);
calpha += dalpha;
}
+ uiWidgetBaseParameters widget_params = {
+ .recti.xmin = rct->xmin, .recti.ymin = rct->ymin,
+ .recti.xmax = rct->xmax, .recti.ymax = rct->ymax - 10.0f,
+ .rect.xmin = rct->xmin - a, .rect.ymin = rct->ymin - a,
+ .rect.xmax = rct->xmax + a, .rect.ymax = rct->ymax - 10.0f + a,
+ .radi = rad,
+ .rad = rad + a,
+ .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
+ .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
+ };
+
+ Gwn_Batch *batch = ui_batch_roundbox_shadow_get();
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_SHADOW);
+ GWN_batch_uniform_4fv_array(batch, "parameters", 4, (float *)&widget_params);
+ GWN_batch_uniform_1f(batch, "alpha", 1.0f - visibility);
+ GWN_batch_draw(batch);
+
/* outline emphasis */
glEnable(GL_LINE_SMOOTH);
float color[4] = {0.0f, 0.0f, 0.0f, 0.4f};
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 3af64c8c5a6..11f78967315 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -74,7 +74,7 @@
#include "BKE_paint.h"
#include "ED_screen.h"
-#include "ED_util.h"
+#include "ED_undo.h"
#include "ED_keyframing.h"
#include "UI_interface.h"
@@ -185,6 +185,7 @@ typedef struct uiSelectContextStore {
uiSelectContextElem *elems;
int elems_len;
bool do_free;
+ bool is_enabled;
/* When set, simply copy values (don't apply difference).
* Rules are:
* - dragging numbers uses delta.
@@ -200,9 +201,7 @@ static void ui_selectcontext_apply(
bContext *C, uiBut *but, struct uiSelectContextStore *selctx_data,
const double value, const double value_orig);
-#if 0
#define IS_ALLSELECT_EVENT(event) ((event)->alt != 0)
-#endif
/** just show a tinted color so users know its activated */
#define UI_BUT_IS_SELECT_CONTEXT UI_BUT_NODE_ACTIVE
@@ -1180,11 +1179,14 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl
ui_but_execute_begin(C, ar, but, &active_back);
#ifdef USE_ALLSELECT
- if (mbut_state->select_others.elems_len == 0) {
- ui_selectcontext_begin(C, but, &mbut_state->select_others);
- }
- if (mbut_state->select_others.elems_len == 0) {
- mbut_state->select_others.elems_len = -1;
+ if (data->select_others.is_enabled) {
+ /* init once! */
+ if (mbut_state->select_others.elems_len == 0) {
+ ui_selectcontext_begin(C, but, &mbut_state->select_others);
+ }
+ if (mbut_state->select_others.elems_len == 0) {
+ mbut_state->select_others.elems_len = -1;
+ }
}
/* needed so we apply the right deltas */
@@ -2067,7 +2069,12 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
else
# endif
if (data->select_others.elems_len == 0) {
- ui_selectcontext_begin(C, but, &data->select_others);
+ wmWindow *win = CTX_wm_window(C);
+ /* may have been enabled before activating */
+ if (data->select_others.is_enabled || IS_ALLSELECT_EVENT(win->eventstate)) {
+ ui_selectcontext_begin(C, but, &data->select_others);
+ data->select_others.is_enabled = true;
+ }
}
if (data->select_others.elems_len == 0) {
/* dont check again */
@@ -3070,7 +3077,11 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
#ifdef USE_ALLSELECT
if (is_num_but) {
- data->select_others.is_copy = true;
+ if (IS_ALLSELECT_EVENT(win->eventstate)) {
+ data->select_others.is_enabled = true;
+ data->select_others.is_copy = true;
+
+ }
}
#endif
@@ -3675,6 +3686,15 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat
data->menu->popup = but->block->handle->popup;
}
+#ifdef USE_ALLSELECT
+ {
+ wmWindow *win = CTX_wm_window(C);
+ if (IS_ALLSELECT_EVENT(win->eventstate)) {
+ data->select_others.is_enabled = true;
+ }
+ }
+#endif
+
/* this makes adjacent blocks auto open from now on */
//if (but->block->auto_open == 0) but->block->auto_open = 1;
}
@@ -3859,7 +3879,7 @@ static int ui_do_but_KEYEVT(
static int ui_do_but_TAB(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_RELEASE) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
return WM_UI_HANDLER_CONTINUE;
}
@@ -6793,11 +6813,11 @@ static bool ui_but_menu(bContext *C, uiBut *but)
const PropertySubType subtype = RNA_property_subtype(prop);
bool is_anim = RNA_property_animateable(ptr, prop);
bool is_editable = RNA_property_editable(ptr, prop);
- bool is_overridable;
/*bool is_idprop = RNA_property_is_idprop(prop);*/ /* XXX does not work as expected, not strictly needed */
bool is_set = RNA_property_is_set(ptr, prop);
- RNA_property_override_status(ptr, prop, -1, &is_overridable, NULL, NULL, NULL);
+ const int override_status = RNA_property_override_status(ptr, prop, -1);
+ const bool is_overridable = (override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0;
/* second slower test, saved people finding keyframe items in menus when its not possible */
if (is_anim)
@@ -7762,7 +7782,10 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
/* highlight has timers for tooltips and auto open */
if (state == BUTTON_STATE_HIGHLIGHT) {
- but->flag &= ~UI_SELECT;
+ /* for list-items (that are not drawn with regular emboss), don't change selection based on hovering */
+ if (((but->flag & UI_BUT_LIST_ITEM) == 0) && (but->dragflag & UI_EMBOSS_NONE)) {
+ but->flag &= ~UI_SELECT;
+ }
button_tooltip_timer_reset(C, but);
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index d048324d35e..682eac6a352 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -34,11 +34,13 @@
#include "MEM_guardedalloc.h"
#include "GPU_draw.h"
+#include "GPU_matrix.h"
#include "GPU_immediate.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_fileops_types.h"
+#include "BLI_math_vector.h"
#include "DNA_brush_types.h"
#include "DNA_curve_types.h"
@@ -46,6 +48,7 @@
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
+#include "DNA_workspace_types.h"
#include "RNA_access.h"
#include "RNA_enum_types.h"
@@ -61,6 +64,8 @@
#include "BIF_glutil.h"
+#include "DEG_depsgraph.h"
+
#include "ED_datafiles.h"
#include "ED_keyframes_draw.h"
#include "ED_render.h"
@@ -1004,6 +1009,9 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect),
rect = ima->rect;
}
+ /* We need to flush widget base first to ensure correct ordering. */
+ UI_widgetbase_draw_cache_flush();
+
/* draw */
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
immDrawPixelsTex(&state, draw_x, draw_y, draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect,
@@ -1013,10 +1021,122 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect),
IMB_freeImBuf(ima);
}
-static void icon_draw_texture(
+/* High enough to make a difference, low enough so that
+ * small draws are still efficient with the use of glUniform.
+ * NOTE TODO: We could use UBO but we would need some triple
+ * buffer system + persistent mapping for this to be more
+ * efficient than simple glUniform calls. */
+#define ICON_DRAW_CACHE_SIZE 16
+
+typedef struct IconDrawCall{
+ rctf pos;
+ rctf tex;
+ float color[4];
+} IconDrawCall;
+
+static struct {
+ IconDrawCall drawcall_cache[ICON_DRAW_CACHE_SIZE];
+ int calls; /* Number of calls batched together */
+ bool enabled;
+ float mat[4][4];
+} g_icon_draw_cache = {0};
+
+void UI_icon_draw_cache_begin(void)
+{
+ BLI_assert(g_icon_draw_cache.enabled == false);
+ g_icon_draw_cache.enabled = true;
+}
+
+static void icon_draw_cache_flush_ex(void)
+{
+ if (g_icon_draw_cache.calls == 0)
+ return;
+
+ /* We need to flush widget base first to ensure correct ordering. */
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ UI_widgetbase_draw_cache_flush();
+
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, icongltex.id);
+
+ GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR);
+ GPU_shader_bind(shader);
+
+ int img_loc = GPU_shader_get_uniform(shader, "image");
+ int data_loc = GPU_shader_get_uniform(shader, "calls_data[0]");
+
+ glUniform1i(img_loc, 0);
+ glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)g_icon_draw_cache.drawcall_cache);
+
+ GWN_draw_primitive(GWN_PRIM_TRIS, 6 * g_icon_draw_cache.calls);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ g_icon_draw_cache.calls = 0;
+}
+
+void UI_icon_draw_cache_end(void)
+{
+ BLI_assert(g_icon_draw_cache.enabled == true);
+ g_icon_draw_cache.enabled = false;
+
+ /* Don't change blend state if it's not needed. */
+ if (g_icon_draw_cache.calls == 0)
+ return;
+
+ glEnable(GL_BLEND);
+
+ icon_draw_cache_flush_ex();
+
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_BLEND);
+}
+
+static void icon_draw_texture_cached(
float x, float y, float w, float h, int ix, int iy,
int UNUSED(iw), int ih, float alpha, const float rgb[3])
{
+
+ float mvp[4][4];
+ gpuGetModelViewProjectionMatrix(mvp);
+
+ IconDrawCall *call = &g_icon_draw_cache.drawcall_cache[g_icon_draw_cache.calls];
+ g_icon_draw_cache.calls++;
+
+ /* Manual mat4*vec2 */
+ call->pos.xmin = x * mvp[0][0] + y * mvp[1][0] + mvp[3][0];
+ call->pos.ymin = x * mvp[0][1] + y * mvp[1][1] + mvp[3][1];
+ call->pos.xmax = call->pos.xmin + w * mvp[0][0] + h * mvp[1][0];
+ call->pos.ymax = call->pos.ymin + w * mvp[0][1] + h * mvp[1][1];
+
+ call->tex.xmin = ix * icongltex.invw;
+ call->tex.xmax = (ix + ih) * icongltex.invw;
+ call->tex.ymin = iy * icongltex.invh;
+ call->tex.ymax = (iy + ih) * icongltex.invh;
+
+ if (rgb) copy_v4_fl4(call->color, rgb[0], rgb[1], rgb[2], alpha);
+ else copy_v4_fl(call->color, alpha);
+
+ if (g_icon_draw_cache.calls == ICON_DRAW_CACHE_SIZE) {
+ icon_draw_cache_flush_ex();
+ }
+}
+
+static void icon_draw_texture(
+ float x, float y, float w, float h, int ix, int iy,
+ int iw, int ih, float alpha, const float rgb[3])
+{
+ if (g_icon_draw_cache.enabled) {
+ icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb);
+ return;
+ }
+
+ /* We need to flush widget base first to ensure correct ordering. */
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ UI_widgetbase_draw_cache_flush();
+
float x1, x2, y1, y2;
x1 = ix * icongltex.invw;
@@ -1024,32 +1144,20 @@ static void icon_draw_texture(
y1 = iy * icongltex.invh;
y2 = (iy + ih) * icongltex.invh;
+ glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, icongltex.id);
- Gwn_VertFormat *format = immVertexFormat();
- unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned int texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
- if (rgb) immUniformColor3fvAlpha(rgb, alpha);
- else immUniformColor4f(alpha, alpha, alpha, alpha);
+ GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
+ GPU_shader_bind(shader);
- immUniform1i("image", 0);
+ if (rgb) glUniform4f(GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_COLOR), rgb[0], rgb[1], rgb[2], alpha);
+ else glUniform4f(GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_COLOR), alpha, alpha, alpha, alpha);
- immBegin(GWN_PRIM_TRI_STRIP, 4);
- immAttrib2f(texCoord, x1, y2);
- immVertex2f(pos, x, y + h);
+ glUniform1i(GPU_shader_get_uniform(shader, "image"), 0);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), x1, y1, x2, y2);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), x, y, x + w, y + h);
- immAttrib2f(texCoord, x1, y1);
- immVertex2f(pos, x, y);
-
- immAttrib2f(texCoord, x2, y2);
- immVertex2f(pos, x + w, y + h);
-
- immAttrib2f(texCoord, x2, y1);
- immVertex2f(pos, x + w, y);
- immEnd();
-
- immUnbindProgram();
+ GWN_draw_primitive(GWN_PRIM_TRI_STRIP, 4);
glBindTexture(GL_TEXTURE_2D, 0);
}
@@ -1112,7 +1220,7 @@ static void icon_draw_size(
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
icon_draw_texture(x, y, (float)w, (float)h, di->data.texture.x, di->data.texture.y,
di->data.texture.w, di->data.texture.h, alpha, rgb);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
else if (di->type == ICON_TYPE_BUFFER) {
/* it is a builtin icon */
@@ -1122,9 +1230,9 @@ static void icon_draw_size(
#endif
if (!iimg->rect) return; /* something has gone wrong! */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, rgb, is_preview);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
else if (di->type == ICON_TYPE_PREVIEW) {
PreviewImage *pi = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
@@ -1137,7 +1245,7 @@ static void icon_draw_size(
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
icon_draw_rect(x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], alpha, rgb, is_preview);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
}
}
@@ -1316,7 +1424,7 @@ int UI_idcode_icon_get(const int idcode)
{
switch (idcode) {
case ID_AC:
- return ICON_ANIM_DATA;
+ return ICON_ACTION;
case ID_AR:
return ICON_ARMATURE_DATA;
case ID_BR:
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 8d7f9d47ab5..043dfc9fd99 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -700,6 +700,35 @@ struct wmIMEData *ui_but_ime_data_get(uiBut *but);
#endif
/* interface_widgets.c */
+
+/* Widget shader parameters, must match the shader layout. */
+typedef struct uiWidgetBaseParameters {
+ rctf recti, rect;
+ float radi, rad;
+ float facxi, facyi;
+ float round_corners[4];
+ float color_inner1[4], color_inner2[4];
+ float color_outline[4], color_emboss[4];
+ float color_tria[4];
+ float tria1_center[2], tria2_center[2];
+ float tria1_size, tria2_size;
+ float shade_dir, do_alpha_check;
+} uiWidgetBaseParameters;
+
+enum {
+ ROUNDBOX_TRIA_NONE = 0,
+ ROUNDBOX_TRIA_ARROWS,
+ ROUNDBOX_TRIA_SCROLL,
+ ROUNDBOX_TRIA_MENU,
+ ROUNDBOX_TRIA_CHECK,
+
+ ROUNDBOX_TRIA_MAX, /* don't use */
+};
+
+struct Gwn_Batch *ui_batch_roundbox_get(bool filled, bool antialiased);
+struct Gwn_Batch *ui_batch_roundbox_widget_get(int tria);
+struct Gwn_Batch *ui_batch_roundbox_shadow_get(void);
+
void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3, const float color[4]);
void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy,
float rad, bool use_alpha, const float color[4]);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 30a18ddc8bc..969367f485c 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -1488,7 +1488,7 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
}
/* Mark non-embossed textfields inside a listbox. */
- if (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->type == UI_BTYPE_TEXT) && (but->dt & UI_EMBOSS_NONE)) {
+ if (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->dt & UI_EMBOSS_NONE)) {
UI_but_flag_enable(but, UI_BUT_LIST_ITEM);
}
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 16525dfbc9e..9e31e8729d5 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -482,13 +482,12 @@ static int override_type_set_button_poll(bContext *C)
PointerRNA ptr;
PropertyRNA *prop;
int index;
- bool is_overridable;
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- RNA_property_override_status(&ptr, prop, index, &is_overridable, NULL, NULL, NULL);
+ const int override_status = RNA_property_override_status(&ptr, prop, index);
- return (ptr.data && prop && is_overridable);
+ return (ptr.data && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE));
}
static int override_type_set_button_exec(bContext *C, wmOperator *op)
@@ -572,13 +571,12 @@ static int override_remove_button_poll(bContext *C)
PointerRNA ptr;
PropertyRNA *prop;
int index;
- bool is_overridden;
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- RNA_property_override_status(&ptr, prop, index, NULL, &is_overridden, NULL, NULL);
+ const int override_status = RNA_property_override_status(&ptr, prop, index);
- return (ptr.data && ptr.id.data && prop && is_overridden);
+ return (ptr.data && ptr.id.data && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDDEN));
}
static int override_remove_button_exec(bContext *C, wmOperator *op)
@@ -945,7 +943,8 @@ static int reports_to_text_exec(bContext *C, wmOperator *UNUSED(op))
str = BKE_reports_string(reports, (G.debug & G_DEBUG) ? RPT_DEBUG : RPT_INFO);
if (str) {
- BKE_text_write(txt, str);
+ TextUndoBuf *utxt = NULL; // FIXME
+ BKE_text_write(txt, utxt, str);
MEM_freeN(str);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index c3759e232b0..bb086d63917 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -501,9 +501,28 @@ static void ui_draw_panel_scalewidget(unsigned int pos, const rcti *rect)
glDisable(GL_BLEND);
}
-static void ui_draw_panel_dragwidget(unsigned int pos, const rctf *rect)
+
+static void immRectf_tris_color_ex(unsigned int pos, float x1, float y1, float x2, float y2,
+ unsigned int col, const float color[3])
+{
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x1, y1);
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x2, y1);
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x2, y2);
+
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x1, y1);
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x2, y2);
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x1, y2);
+}
+
+static void ui_draw_panel_dragwidget(unsigned int pos, unsigned int col, const rctf *rect)
{
- unsigned char col_back[3], col_high[3], col_dark[3];
+ float col_high[4], col_dark[4];
const int col_tint = 84;
const int px = (int)U.pixelsize;
@@ -518,24 +537,24 @@ static void ui_draw_panel_dragwidget(unsigned int pos, const rctf *rect)
const int x_ofs = y_ofs;
int i_x, i_y;
-
- UI_GetThemeColor3ubv(UI_GetThemeValue(TH_PANEL_SHOW_HEADER) ? TH_PANEL_HEADER : TH_PANEL_BACK, col_back);
- UI_GetColorPtrShade3ubv(col_back, col_high, col_tint);
- UI_GetColorPtrShade3ubv(col_back, col_dark, -col_tint);
-
+ int col_id = UI_GetThemeValue(TH_PANEL_SHOW_HEADER) ? TH_PANEL_HEADER : TH_PANEL_BACK;
+ UI_GetThemeColorShade4fv(col_id, col_tint, col_high);
+ UI_GetThemeColorShade4fv(col_id, -col_tint, col_dark);
/* draw multiple boxes */
+ immBegin(GWN_PRIM_TRIS, 4 * 2 * (6 * 2));
for (i_x = 0; i_x < 4; i_x++) {
for (i_y = 0; i_y < 2; i_y++) {
const int x_co = (x_min + x_ofs) + (i_x * (box_size + box_margin));
const int y_co = (y_min + y_ofs) + (i_y * (box_size + box_margin));
- immUniformColor3ubv(col_dark);
- immRectf(pos, x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom);
- immUniformColor3ubv(col_high);
- immRectf(pos, x_co - box_size, y_co, x_co, y_co + box_size);
+ immRectf_tris_color_ex(pos, x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom,
+ col, col_dark);
+ immRectf_tris_color_ex(pos, x_co - box_size, y_co, x_co, y_co + box_size,
+ col, col_high);
}
}
+ immEnd();
}
@@ -662,8 +681,11 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
/* horizontal title */
if (is_closed_x == false) {
+ unsigned int col;
ui_draw_aligned_panel_header(style, block, &headrect, 'h');
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ Gwn_VertFormat *format = immVertexFormat();
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
/* itemrect smaller */
itemrect.xmax = headrect.xmax - 5.0f / block->aspect;
@@ -672,9 +694,12 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
itemrect.ymax = headrect.ymax;
BLI_rctf_scale(&itemrect, 0.7f);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- ui_draw_panel_dragwidget(pos, &itemrect);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ ui_draw_panel_dragwidget(pos, col, &itemrect);
immUnbindProgram();
+
+ /* Restore format for the following draws. */
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
}
/* if the panel is minimized vertically:
@@ -1594,30 +1619,36 @@ static void ui_panel_category_draw_tab(
immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_STRIP, vert_ct);
- immAttrib3ubv(color, col);
-
/* start with corner right-top */
if (use_highlight) {
if (roundboxtype & UI_CNR_TOP_RIGHT) {
+ immAttrib3ubv(color, col);
immVertex2f(pos, maxx, maxy - rad);
for (a = 0; a < 4; a++) {
+ immAttrib3ubv(color, col);
immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
}
+ immAttrib3ubv(color, col);
immVertex2f(pos, maxx - rad, maxy);
}
else {
+ immAttrib3ubv(color, col);
immVertex2f(pos, maxx, maxy);
}
/* corner left-top */
if (roundboxtype & UI_CNR_TOP_LEFT) {
+ immAttrib3ubv(color, col);
immVertex2f(pos, minx + rad, maxy);
for (a = 0; a < 4; a++) {
+ immAttrib3ubv(color, col);
immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
}
+ immAttrib3ubv(color, col);
immVertex2f(pos, minx, maxy - rad);
}
else {
+ immAttrib3ubv(color, col);
immVertex2f(pos, minx, maxy);
}
}
@@ -1626,6 +1657,9 @@ static void ui_panel_category_draw_tab(
if (highlight_fade) {
immAttrib3ubv(color, highlight_fade);
}
+ else {
+ immAttrib3ubv(color, col);
+ }
immVertex2f(pos, minx, miny + rad);
immEnd();
immUnbindProgram();
@@ -1634,25 +1668,33 @@ static void ui_panel_category_draw_tab(
/* corner left-bottom */
if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
+ immAttrib3ubv(color, col);
immVertex2f(pos, minx, miny + rad);
for (a = 0; a < 4; a++) {
+ immAttrib3ubv(color, col);
immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
}
+ immAttrib3ubv(color, col);
immVertex2f(pos, minx + rad, miny);
}
else {
+ immAttrib3ubv(color, col);
immVertex2f(pos, minx, miny);
}
/* corner right-bottom */
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
+ immAttrib3ubv(color, col);
immVertex2f(pos, maxx - rad, miny);
for (a = 0; a < 4; a++) {
+ immAttrib3ubv(color, col);
immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
}
+ immAttrib3ubv(color, col);
immVertex2f(pos, maxx, miny + rad);
}
else {
+ immAttrib3ubv(color, col);
immVertex2f(pos, maxx, miny);
}
diff --git a/source/blender/editors/interface/interface_region_menu_pie.c b/source/blender/editors/interface/interface_region_menu_pie.c
index b3d5c74f77a..37a603d967f 100644
--- a/source/blender/editors/interface/interface_region_menu_pie.c
+++ b/source/blender/editors/interface/interface_region_menu_pie.c
@@ -214,9 +214,10 @@ int UI_pie_menu_invoke(struct bContext *C, const char *idname, const wmEvent *ev
return OPERATOR_CANCELLED;
}
- if (mt->poll && mt->poll(C, mt) == 0)
+ if (WM_menutype_poll(C, mt) == false) {
/* cancel but allow event to pass through, just like operators do */
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
pie = UI_pie_menu_begin(C, IFACE_(mt->label), ICON_NONE, event);
layout = UI_pie_menu_layout(pie);
diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c
index a0aecb12b84..d4fe0f5a5ee 100644
--- a/source/blender/editors/interface/interface_region_menu_popup.c
+++ b/source/blender/editors/interface/interface_region_menu_popup.c
@@ -518,9 +518,10 @@ int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports)
return OPERATOR_CANCELLED;
}
- if (mt->poll && mt->poll(C, mt) == 0)
+ if (WM_menutype_poll(C, mt) == false) {
/* cancel but allow event to pass through, just like operators do */
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
pup = UI_popup_menu_begin(C, IFACE_(mt->label), ICON_NONE);
layout = UI_popup_menu_layout(pup);
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c
index 24990c593ac..67383ec73a6 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.c
@@ -48,7 +48,6 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "wm_subwindow.h"
#include "UI_interface.h"
@@ -303,19 +302,36 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
static void ui_block_region_draw(const bContext *C, ARegion *ar)
{
+ ScrArea *ctx_area = CTX_wm_area(C);
+ ARegion *ctx_region = CTX_wm_region(C);
uiBlock *block;
if (ar->do_draw & RGN_DRAW_REFRESH_UI) {
+ ScrArea *handle_ctx_area;
+ ARegion *handle_ctx_region;
uiBlock *block_next;
+
ar->do_draw &= ~RGN_DRAW_REFRESH_UI;
for (block = ar->uiblocks.first; block; block = block_next) {
block_next = block->next;
if (block->handle->can_refresh) {
+ handle_ctx_area = block->handle->ctx_area;
+ handle_ctx_region = block->handle->ctx_region;
+
+ if (handle_ctx_area) {
+ CTX_wm_area_set((bContext *)C, handle_ctx_area);
+ }
+ if (handle_ctx_region) {
+ CTX_wm_region_set((bContext *)C, handle_ctx_region);
+ }
ui_popup_block_refresh((bContext *)C, block->handle, NULL, NULL);
}
}
}
+ CTX_wm_area_set((bContext *)C, ctx_area);
+ CTX_wm_region_set((bContext *)C, ctx_region);
+
for (block = ar->uiblocks.first; block; block = block->next)
UI_block_draw(C, block);
}
@@ -589,9 +605,7 @@ uiBlock *ui_popup_block_refresh(
ED_region_init(C, ar);
/* get winmat now that we actually have the subwindow */
- wmSubWindowSet(window, ar->swinid);
-
- wm_subwindow_matrix_get(window, ar->swinid, block->winmat);
+ wmGetProjectionMatrix(block->winmat, &ar->winrct);
/* notify change and redraw */
ED_region_tag_redraw(ar);
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index 07fbefa42e1..449e783b03e 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -175,12 +175,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
float background_color[3];
float tone_bg;
- int i, multisample_enabled;
-
- /* disable AA, makes widgets too blurry */
- multisample_enabled = glIsEnabled(GL_MULTISAMPLE);
- if (multisample_enabled)
- glDisable(GL_MULTISAMPLE);
+ int i;
wmOrtho2_region_pixelspace(ar);
@@ -285,9 +280,6 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
BLF_disable(data->fstyle.uifont_id, BLF_WORD_WRAP);
BLF_disable(blf_mono_font, BLF_WORD_WRAP);
-
- if (multisample_enabled)
- glEnable(GL_MULTISAMPLE);
}
static void ui_tooltip_region_free_cb(ARegion *ar)
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 32758b7935a..375027a84d0 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -36,7 +36,7 @@
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_brush_types.h"
#include "DNA_texture_types.h"
@@ -79,7 +79,7 @@
#include "ED_screen.h"
#include "ED_object.h"
#include "ED_render.h"
-#include "ED_util.h"
+#include "ED_undo.h"
#include "RNA_access.h"
@@ -351,11 +351,11 @@ static void id_search_cb_objects_from_scene(const bContext *C, void *arg_templat
BKE_main_id_flag_listbase(lb, LIB_TAG_DOIT, false);
- FOREACH_SCENE_OBJECT(scene, ob_iter)
+ FOREACH_SCENE_OBJECT_BEGIN(scene, ob_iter)
{
ob_iter->id.tag |= LIB_TAG_DOIT;
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
id_search_cb_tagged(C, arg_template, str, items);
}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 3afae5ed8d4..5a210d01f27 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -55,6 +55,7 @@
#include "interface_intern.h"
#include "GPU_basic_shader.h"
+#include "GPU_batch.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
@@ -79,6 +80,7 @@ enum {
#define UI_BUT_UPDATE_DELAY ((void)0)
#define UI_BUT_UNDO ((void)0)
+
/* ************** widget base functions ************** */
/**
* - in: roundbox codes for corner types and radius
@@ -98,6 +100,8 @@ enum {
typedef struct uiWidgetTrias {
unsigned int tot;
+ int type;
+ float size, center[2];
float vec[16][2];
const unsigned int (*index)[3];
@@ -105,21 +109,24 @@ typedef struct uiWidgetTrias {
} uiWidgetTrias;
/* max as used by round_box__edges */
+/* Make sure to change widget_base_vert.glsl accordingly. */
#define WIDGET_CURVE_RESOLU 9
#define WIDGET_SIZE_MAX (WIDGET_CURVE_RESOLU * 4)
typedef struct uiWidgetBase {
-
+ /* TODO remove these completely */
int totvert, halfwayvert;
float outer_v[WIDGET_SIZE_MAX][2];
float inner_v[WIDGET_SIZE_MAX][2];
float inner_uv[WIDGET_SIZE_MAX][2];
- bool draw_inner, draw_outline, draw_emboss, draw_shadedir;
+ bool draw_inner, draw_outline, draw_emboss;
uiWidgetTrias tria1;
uiWidgetTrias tria2;
-
+
+ /* Widget shader parameters, must match the shader layout. */
+ uiWidgetBaseParameters uniform_params;
} uiWidgetBase;
/** uiWidgetType: for time being only for visual appearance,
@@ -206,6 +213,270 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}}
/** \} */
+/* **************** Batch creations ****************** */
+/**
+ * In order to speed up UI drawing we create some batches that are then
+ * modified by specialized shaders to draw certain elements really fast.
+ * TODO: find a better place. Maybe it's own file?
+ **/
+
+/* offset in triavec[] in shader per type */
+static const int tria_ofs[ROUNDBOX_TRIA_MAX] = {0, 0, 6, 22, 28};
+static const int tria_vcount[ROUNDBOX_TRIA_MAX] = {0, 3, 16, 3, 6};
+
+static struct {
+ Gwn_Batch *roundbox_widget[ROUNDBOX_TRIA_MAX];
+
+ Gwn_Batch *roundbox_simple;
+ Gwn_Batch *roundbox_simple_aa;
+ Gwn_Batch *roundbox_simple_outline;
+ Gwn_Batch *roundbox_shadow;
+
+ Gwn_VertFormat format;
+ uint vflag_id;
+} g_ui_batch_cache = {{0}};
+
+static Gwn_VertFormat *vflag_format(void)
+{
+ if (g_ui_batch_cache.format.attrib_ct == 0) {
+ Gwn_VertFormat *format = &g_ui_batch_cache.format;
+ g_ui_batch_cache.vflag_id = GWN_vertformat_attr_add(format, "vflag", GWN_COMP_U32, 1, GWN_FETCH_INT);
+ }
+ return &g_ui_batch_cache.format;
+}
+
+#define INNER 0
+#define OUTLINE 1
+#define EMBOSS 2
+#define NO_AA WIDGET_AA_JITTER
+
+static void set_roundbox_vertex_data(
+ Gwn_VertBufRaw *vflag_step, uint32_t d)
+{
+ uint32_t *data = GWN_vertbuf_raw_step(vflag_step);
+ *data = d;
+}
+
+static uint32_t set_roundbox_vertex(
+ Gwn_VertBufRaw *vflag_step,
+ int corner_id, int corner_v, int jit_v, bool inner, bool emboss, int color)
+{
+ uint32_t *data = GWN_vertbuf_raw_step(vflag_step);
+ *data = corner_id;
+ *data |= corner_v << 2;
+ *data |= jit_v << 6;
+ *data |= color << 12;
+ *data |= (inner) ? (1 << 10) : 0; /* is inner vert */
+ *data |= (emboss) ? (1 << 11) : 0; /* is emboss vert */
+ return *data;
+}
+
+static uint32_t set_tria_vertex(
+ Gwn_VertBufRaw *vflag_step,
+ int tria_type, int tria_v, int tria_id, int jit_v)
+{
+ uint32_t *data = GWN_vertbuf_raw_step(vflag_step);
+ if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS, ROUNDBOX_TRIA_MENU)) {
+ tria_v += tria_id * 3;
+ }
+ *data = tria_ofs[tria_type] + tria_v;
+ *data |= jit_v << 6;
+ *data |= (tria_id == 0) ? (1 << 10) : 0; /* is first tria */
+ *data |= 1 << 14; /* is tria vert */
+ return *data;
+}
+
+static void roundbox_batch_add_tria(Gwn_VertBufRaw *vflag_step, int tria, uint32_t last_data)
+{
+ const int tria_num = (tria == ROUNDBOX_TRIA_CHECK) ? 1 : 2;
+ /* for each tria */
+ for (int t = 0; t < tria_num; ++t) {
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ /* restart */
+ set_roundbox_vertex_data(vflag_step, last_data);
+ set_tria_vertex(vflag_step, tria, 0, t, j);
+ for (int v = 0; v < tria_vcount[tria]; v++) {
+ last_data = set_tria_vertex(vflag_step, tria, v, t, j);
+ }
+ }
+ }
+}
+
+Gwn_Batch *ui_batch_roundbox_widget_get(int tria)
+{
+ if (g_ui_batch_cache.roundbox_widget[tria] == NULL) {
+ uint32_t last_data;
+ Gwn_VertBufRaw vflag_step;
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(vflag_format());
+ int vcount = WIDGET_SIZE_MAX; /* inner */
+ vcount += 2; /* restart */
+ vcount += ((WIDGET_SIZE_MAX + 1) * 2) * WIDGET_AA_JITTER; /* outline (edges) */
+ vcount += 2; /* restart */
+ vcount += ((WIDGET_CURVE_RESOLU * 2) * 2) * WIDGET_AA_JITTER; /* emboss */
+ if (tria) {
+ vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria1 */
+ if (tria != ROUNDBOX_TRIA_CHECK) {
+ vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria2 */
+ }
+ }
+ GWN_vertbuf_data_alloc(vbo, vcount);
+ GWN_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
+ /* Inner */
+ for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
+ for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU -1; a2 >= 0; a1++, a2--) {
+ last_data = set_roundbox_vertex(&vflag_step, c1, a1, NO_AA, true, false, INNER);
+ last_data = set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER);
+ }
+ }
+ /* restart */
+ set_roundbox_vertex_data(&vflag_step, last_data);
+ set_roundbox_vertex(&vflag_step, 0, 0, 0, true, false, OUTLINE);
+ /* Outlines */
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ for (int c = 0; c < 4; c++) {
+ for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
+ set_roundbox_vertex(&vflag_step, c, a, j, true, false, OUTLINE);
+ set_roundbox_vertex(&vflag_step, c, a, j, false, false, OUTLINE);
+ }
+ }
+ /* Close the loop. */
+ set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, OUTLINE);
+ last_data = set_roundbox_vertex(&vflag_step, 0, 0, j, false, false, OUTLINE);
+ }
+ /* restart */
+ set_roundbox_vertex_data(&vflag_step, last_data);
+ set_roundbox_vertex(&vflag_step, 0, 0, 0, false, false, EMBOSS);
+ /* Emboss */
+ bool rev = false; /* go back and forth : avoid degenerate triangle (but beware of backface cull) */
+ for (int j = 0; j < WIDGET_AA_JITTER; j++, rev = !rev) {
+ for (int c = (rev) ? 1 : 0; (rev) ? c >= 0 : c < 2; (rev) ? c-- : c++) {
+ int sta = (rev) ? WIDGET_CURVE_RESOLU - 1 : 0;
+ int end = WIDGET_CURVE_RESOLU;
+ for (int a = sta; (rev) ? a >= 0 : a < end; (rev) ? a-- : a++) {
+ set_roundbox_vertex(&vflag_step, c, a, j, false, false, EMBOSS);
+ last_data = set_roundbox_vertex(&vflag_step, c, a, j, false, true, EMBOSS);
+ }
+ }
+ }
+ if (tria) {
+ roundbox_batch_add_tria(&vflag_step, tria, last_data);
+ }
+ g_ui_batch_cache.roundbox_widget[tria] = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ gpu_batch_presets_register(g_ui_batch_cache.roundbox_widget[tria]);
+ }
+ return g_ui_batch_cache.roundbox_widget[tria];
+}
+
+Gwn_Batch *ui_batch_roundbox_get(bool filled, bool antialiased)
+{
+ Gwn_Batch **batch = NULL;
+
+ if (filled) {
+ if (antialiased)
+ batch = &g_ui_batch_cache.roundbox_simple_aa;
+ else
+ batch = &g_ui_batch_cache.roundbox_simple;
+ }
+ else {
+ if (antialiased)
+ BLI_assert(0); /* Use GL_LINE_SMOOTH instead!!: */
+ else
+ batch = &g_ui_batch_cache.roundbox_simple_outline;
+ }
+
+ if (*batch == NULL) {
+ uint32_t last_data;
+ Gwn_VertBufRaw vflag_step;
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(vflag_format());
+ int vcount = WIDGET_SIZE_MAX;
+ vcount += (filled) ? 2 : 0;
+ vcount *= (antialiased) ? WIDGET_AA_JITTER : 1;
+ GWN_vertbuf_data_alloc(vbo, vcount);
+ GWN_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
+
+ if (filled) {
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ if (!antialiased) {
+ j = NO_AA;
+ }
+ /* restart */
+ set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, INNER);
+ for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
+ for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU -1; a2 >= 0; a1++, a2--) {
+ last_data = set_roundbox_vertex(&vflag_step, c1, a1, j, true, false, INNER);
+ last_data = set_roundbox_vertex(&vflag_step, c2, a2, j, true, false, INNER);
+ }
+ }
+ /* restart */
+ set_roundbox_vertex_data(&vflag_step, last_data);
+ if (!antialiased) {
+ break;
+ }
+ }
+ *batch = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ else {
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ if (!antialiased) {
+ j = NO_AA;
+ }
+ for (int c = 0; c < 4; c++) {
+ for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
+ set_roundbox_vertex(&vflag_step, c, a, j, true, false, INNER);
+ }
+ }
+ if (!antialiased) {
+ break;
+ }
+ }
+ *batch = GWN_batch_create_ex(GWN_PRIM_LINE_LOOP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+
+ gpu_batch_presets_register(*batch);
+ }
+ return *batch;
+}
+
+Gwn_Batch *ui_batch_roundbox_shadow_get(void)
+{
+ if (g_ui_batch_cache.roundbox_shadow == NULL) {
+ uint32_t last_data;
+ Gwn_VertBufRaw vflag_step;
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(vflag_format());
+ int vcount = (WIDGET_SIZE_MAX + 1) * 2 + 2 + WIDGET_SIZE_MAX;
+ GWN_vertbuf_data_alloc(vbo, vcount);
+ GWN_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
+
+ for (int c = 0; c < 4; c++) {
+ for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
+ set_roundbox_vertex(&vflag_step, c, a, NO_AA, true, false, INNER);
+ set_roundbox_vertex(&vflag_step, c, a, NO_AA, false, false, INNER);
+ }
+ }
+ /* close loop */
+ last_data = set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, true, false, INNER);
+ last_data = set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, false, false, INNER);
+ /* restart */
+ set_roundbox_vertex_data(&vflag_step, last_data);
+ set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, true, false, INNER);
+ /* filled */
+ for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
+ for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU -1; a2 >= 0; a1++, a2--) {
+ set_roundbox_vertex(&vflag_step, c1, a1, NO_AA, true, false, INNER);
+ set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER);
+ }
+ }
+ g_ui_batch_cache.roundbox_shadow = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ gpu_batch_presets_register(g_ui_batch_cache.roundbox_shadow);
+ }
+ return g_ui_batch_cache.roundbox_shadow;
+}
+
+#undef INNER
+#undef OUTLINE
+#undef EMBOSS
+#undef NO_AA
+
/* ************************************************* */
void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3,
@@ -239,42 +510,20 @@ void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y
glDisable(GL_BLEND);
}
-/* belongs in interface_draw.c, but needs WIDGET_AA_JITTER from this file */
-void UI_draw_roundbox_aa(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4])
-{
- glEnable(GL_BLEND);
-
- if (filled) {
- /* plain antialiased filled box */
- const float alpha = color[3] * 0.125f;
-
- for (int j = 0; j < WIDGET_AA_JITTER; j++) {
- gpuPushMatrix();
- gpuTranslate2fv(jit[j]);
- UI_draw_roundbox_3fvAlpha(true, minx, miny, maxx, maxy, rad, color, alpha);
- gpuPopMatrix();
- }
- }
- else {
- /* plain antialiased unfilled box */
- glEnable(GL_LINE_SMOOTH);
- UI_draw_roundbox_4fv(false, minx, miny, maxx, maxy, rad, color);
- glDisable(GL_LINE_SMOOTH);
- }
-
- glDisable(GL_BLEND);
-}
-
static void widget_init(uiWidgetBase *wtb)
{
wtb->totvert = wtb->halfwayvert = 0;
wtb->tria1.tot = 0;
wtb->tria2.tot = 0;
+ wtb->tria1.type = ROUNDBOX_TRIA_NONE;
+ wtb->tria1.size = 0;
+ wtb->tria2.size = 0;
wtb->draw_inner = true;
wtb->draw_outline = true;
wtb->draw_emboss = true;
- wtb->draw_shadedir = true;
+
+ wtb->uniform_params.shade_dir = 1.0f;
}
/* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */
@@ -381,7 +630,18 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, const rcti *re
if (2.0f * (radi + 1.0f) > minsize)
radi = 0.5f * minsize - U.pixelsize;
-
+
+ wt->uniform_params.rad = rad;
+ wt->uniform_params.radi = radi;
+ wt->uniform_params.facxi = facxi;
+ wt->uniform_params.facyi = facyi;
+ wt->uniform_params.round_corners[0] = (roundboxalign & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f;
+ wt->uniform_params.round_corners[1] = (roundboxalign & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f;
+ wt->uniform_params.round_corners[2] = (roundboxalign & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f;
+ wt->uniform_params.round_corners[3] = (roundboxalign & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f;
+ BLI_rctf_rcti_copy(&wt->uniform_params.rect, rect);
+ BLI_rctf_init(&wt->uniform_params.recti, minxi, maxxi, minyi, maxyi);
+
/* mult */
for (a = 0; a < WIDGET_CURVE_RESOLU; a++) {
veci[a][0] = radi * cornervec[a][0];
@@ -531,18 +791,20 @@ static void shape_preset_init_trias_ex(
/* center position and size */
centx = (float)rect->xmin + 0.4f * minsize;
centy = (float)rect->ymin + 0.5f * minsize;
- sizex = sizey = -0.5f * triasize * minsize;
+ tria->size = sizex = sizey = -0.5f * triasize * minsize;
if (where == 'r') {
centx = (float)rect->xmax - 0.4f * minsize;
sizex = -sizex;
}
else if (where == 't') {
+ centx = (float)rect->xmin + 0.5f * minsize;
centy = (float)rect->ymax - 0.5f * minsize;
sizey = -sizey;
i2 = 0; i1 = 1;
}
else if (where == 'b') {
+ centx = (float)rect->xmin + 0.5f * minsize;
sizex = -sizex;
i2 = 0; i1 = 1;
}
@@ -552,12 +814,16 @@ static void shape_preset_init_trias_ex(
tria->vec[a][1] = sizey * verts[a][i2] + centy;
}
+ tria->center[0] = centx;
+ tria->center[1] = centy;
+
tria->tot = tris_tot;
tria->index = tris;
}
static void shape_preset_init_number_arrows(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
{
+ tria->type = ROUNDBOX_TRIA_ARROWS;
shape_preset_init_trias_ex(
tria, rect, triasize, where,
g_shape_preset_number_arrow_vert, ARRAY_SIZE(g_shape_preset_number_arrow_vert),
@@ -574,19 +840,22 @@ static void shape_preset_init_hold_action(uiWidgetTrias *tria, const rcti *rect,
static void shape_preset_init_scroll_circle(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
{
+ tria->type = ROUNDBOX_TRIA_SCROLL;
shape_preset_init_trias_ex(
tria, rect, triasize, where,
g_shape_preset_scroll_circle_vert, ARRAY_SIZE(g_shape_preset_scroll_circle_vert),
g_shape_preset_scroll_circle_face, ARRAY_SIZE(g_shape_preset_scroll_circle_face));
}
-static void shape_preset_draw_trias(uiWidgetTrias *tria, uint pos)
+static void shape_preset_draw_trias_aa(uiWidgetTrias *tria, uint pos)
{
- immBegin(GWN_PRIM_TRIS, tria->tot * 3);
- for (int i = 0; i < tria->tot; ++i)
- for (int j = 0; j < 3; ++j)
- immVertex2fv(pos, tria->vec[tria->index[i][j]]);
- immEnd();
+ for (int k = 0; k < WIDGET_AA_JITTER; k++) {
+ for (int i = 0; i < tria->tot; ++i)
+ for (int j = 0; j < 3; ++j)
+ immVertex2f(pos,
+ tria->vec[tria->index[i][j]][0] + jit[k][0],
+ tria->vec[tria->index[i][j]][1] + jit[k][1]);
+ }
}
static void widget_draw_vertex_buffer(unsigned int pos, unsigned int col, int mode,
@@ -607,11 +876,12 @@ static void shape_preset_trias_from_rect_menu(uiWidgetTrias *tria, const rcti *r
{
float centx, centy, size;
int a;
+ tria->type = ROUNDBOX_TRIA_MENU;
/* center position and size */
- centx = rect->xmax - 0.32f * BLI_rcti_size_y(rect);
- centy = rect->ymin + 0.50f * BLI_rcti_size_y(rect);
- size = 0.4f * BLI_rcti_size_y(rect);
+ tria->center[0] = centx = rect->xmax - 0.32f * BLI_rcti_size_y(rect);
+ tria->center[1] = centy = rect->ymin + 0.50f * BLI_rcti_size_y(rect);
+ tria->size = size = 0.4f * BLI_rcti_size_y(rect);
for (a = 0; a < 6; a++) {
tria->vec[a][0] = size * g_shape_preset_menu_arrow_vert[a][0] + centx;
@@ -626,11 +896,12 @@ static void shape_preset_trias_from_rect_checkmark(uiWidgetTrias *tria, const rc
{
float centx, centy, size;
int a;
+ tria->type = ROUNDBOX_TRIA_CHECK;
/* center position and size */
- centx = rect->xmin + 0.5f * BLI_rcti_size_y(rect);
- centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect);
- size = 0.5f * BLI_rcti_size_y(rect);
+ tria->center[0] = centx = rect->xmin + 0.5f * BLI_rcti_size_y(rect);
+ tria->center[1] = centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect);
+ tria->size = size = 0.5f * BLI_rcti_size_y(rect);
for (a = 0; a < 6; a++) {
tria->vec[a][0] = size * g_shape_preset_checkmark_vert[a][0] + centx;
@@ -680,17 +951,6 @@ static void widget_verts_to_triangle_strip(uiWidgetBase *wtb, const int totvert,
copy_v2_v2(triangle_strip[a * 2 + 1], wtb->inner_v[0]);
}
-static void widget_verts_to_triangle_strip_open(uiWidgetBase *wtb, const int totvert, float triangle_strip[WIDGET_SIZE_MAX * 2][2])
-{
- int a;
- for (a = 0; a < totvert; a++) {
- triangle_strip[a * 2][0] = wtb->outer_v[a][0];
- triangle_strip[a * 2][1] = wtb->outer_v[a][1];
- triangle_strip[a * 2 + 1][0] = wtb->outer_v[a][0];
- triangle_strip[a * 2 + 1][1] = wtb->outer_v[a][1] - 1.0f;
- }
-}
-
static void widgetbase_outline(uiWidgetBase *wtb, unsigned int pos)
{
float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
@@ -699,135 +959,178 @@ static void widgetbase_outline(uiWidgetBase *wtb, unsigned int pos)
widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2);
}
-static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
+static void widgetbase_set_uniform_colors_ubv(
+ uiWidgetBase *wtb,
+ const unsigned char *col1, const unsigned char *col2,
+ const unsigned char *outline,
+ const unsigned char *emboss,
+ const unsigned char *tria,
+ const bool alpha_check)
{
- int j, a;
-
- glEnable(GL_BLEND);
-
- /* backdrop non AA */
- if (wtb->draw_inner) {
- BLI_assert(wtb->totvert != 0);
- if (wcol->shaded == 0) {
- if (wcol->alpha_check) {
- float inner_v_half[WIDGET_SIZE_MAX][2];
- float x_mid = 0.0f; /* used for dumb clamping of values */
-
- unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
+ wtb->uniform_params.do_alpha_check = (float)alpha_check;
+ rgba_float_args_set_ch(wtb->uniform_params.color_inner1, col1[0], col1[1], col1[2], col1[3]);
+ rgba_float_args_set_ch(wtb->uniform_params.color_inner2, col2[0], col2[1], col2[2], col2[3]);
+ rgba_float_args_set_ch(wtb->uniform_params.color_outline, outline[0], outline[1], outline[2], outline[3]);
+ rgba_float_args_set_ch(wtb->uniform_params.color_emboss, emboss[0], emboss[1], emboss[2], emboss[3]);
+ rgba_float_args_set_ch(wtb->uniform_params.color_tria, tria[0], tria[1], tria[2], tria[3]);
+}
- /* checkers */
- immUniform4f("color1", UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, 1.0f);
- immUniform4f("color2", UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 1.0f);
- immUniform1i("size", 8);
+/* keep in sync with shader */
+#define MAX_WIDGET_BASE_BATCH 6
- widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, wtb->inner_v, NULL, wtb->totvert);
+struct {
+ Gwn_Batch *batch; /* Batch type */
+ uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH];
+ int count;
+ bool enabled;
+} g_widget_base_batch = {0};
- immUnbindProgram();
+void UI_widgetbase_draw_cache_flush(void)
+{
+ float checker_params[3] = {UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 8.0f};
- /* alpha fill */
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4ubv((unsigned char *)wcol->inner);
+ if (g_widget_base_batch.count == 0)
+ return;
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ Gwn_Batch *batch = g_widget_base_batch.batch;
+ if (g_widget_base_batch.count == 1) {
+ /* draw single */
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)g_widget_base_batch.params);
+ GWN_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
+ GWN_batch_draw(batch);
+ }
+ else {
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE_INST);
+ GWN_batch_uniform_4fv_array(batch, "parameters", 11 * MAX_WIDGET_BASE_BATCH, (float *)g_widget_base_batch.params);
+ GWN_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
+ gpuBindMatrices(batch->interface);
+ GWN_batch_draw_range_ex(batch, 0, g_widget_base_batch.count, true);
+ GWN_batch_program_use_end(batch);
+ }
+ g_widget_base_batch.count = 0;
+}
- for (a = 0; a < wtb->totvert; a++) {
- x_mid += wtb->inner_v[a][0];
- }
- x_mid /= wtb->totvert;
+void UI_widgetbase_draw_cache_begin(void)
+{
+ BLI_assert(g_widget_base_batch.enabled == false);
+ g_widget_base_batch.enabled = true;
+}
- widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, wtb->inner_v, NULL, wtb->totvert);
+void UI_widgetbase_draw_cache_end(void)
+{
+ BLI_assert(g_widget_base_batch.enabled == true);
+ g_widget_base_batch.enabled = false;
- /* 1/2 solid color */
- immUniformColor3ubv((unsigned char *)wcol->inner);
+ glEnable(GL_BLEND);
- for (a = 0; a < wtb->totvert; a++) {
- inner_v_half[a][0] = MIN2(wtb->inner_v[a][0], x_mid);
- inner_v_half[a][1] = wtb->inner_v[a][1];
- }
+ UI_widgetbase_draw_cache_flush();
- widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, inner_v_half, NULL, wtb->totvert);
+ glDisable(GL_BLEND);
+}
- immUnbindProgram();
- }
- else {
- /* simple fill */
- unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4ubv((unsigned char *)wcol->inner);
+static void draw_widgetbase_batch(Gwn_Batch *batch, uiWidgetBase *wtb)
+{
+ wtb->uniform_params.tria1_size = wtb->tria1.size;
+ wtb->uniform_params.tria2_size = wtb->tria2.size;
+ copy_v2_v2(wtb->uniform_params.tria1_center, wtb->tria1.center);
+ copy_v2_v2(wtb->uniform_params.tria2_center, wtb->tria2.center);
+
+ if (g_widget_base_batch.enabled) {
+ if (g_widget_base_batch.batch == NULL) {
+ g_widget_base_batch.batch = ui_batch_roundbox_widget_get(ROUNDBOX_TRIA_ARROWS);
+ }
- widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, wtb->inner_v, NULL, wtb->totvert);
+ /* draw multi */
+ if (batch != g_ui_batch_cache.roundbox_widget[ROUNDBOX_TRIA_NONE] &&
+ batch != g_widget_base_batch.batch)
+ {
+ /* issue previous calls before changing batch type. */
+ UI_widgetbase_draw_cache_flush();
+ g_widget_base_batch.batch = batch;
+ }
- immUnbindProgram();
- }
+ /* No need to change batch if tria is not visible. Just scale it to 0. */
+ if (batch == g_ui_batch_cache.roundbox_widget[ROUNDBOX_TRIA_NONE]) {
+ wtb->uniform_params.tria1_size = wtb->uniform_params.tria2_size = 0;
}
- else {
- char col1[4], col2[4];
- unsigned char col_array[WIDGET_SIZE_MAX][4];
- unsigned char *col_pt = &col_array[0][0];
- Gwn_VertFormat *format = immVertexFormat();
- unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ g_widget_base_batch.params[g_widget_base_batch.count] = wtb->uniform_params;
+ g_widget_base_batch.count++;
- immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+ if (g_widget_base_batch.count == MAX_WIDGET_BASE_BATCH) {
+ UI_widgetbase_draw_cache_flush();
+ }
+ }
+ else {
+ float checker_params[3] = {UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 8.0f};
+ /* draw single */
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&wtb->uniform_params);
+ GWN_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
+ GWN_batch_draw(batch);
+ }
+}
- shadecolors4(col1, col2, wcol->inner, wcol->shadetop, wcol->shadedown);
+static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
+{
+ unsigned char inner_col1[4] = {0};
+ unsigned char inner_col2[4] = {0};
+ unsigned char emboss_col[4] = {0};
+ unsigned char outline_col[4] = {0};
+ unsigned char tria_col[4] = {0};
+ /* For color widget. */
+ bool alpha_check = (wcol->alpha_check && (wcol->shaded == 0));
- for (a = 0; a < wtb->totvert; a++, col_pt += 4) {
- round_box_shade_col4_r(col_pt, col1, col2, wtb->inner_uv[a][wtb->draw_shadedir ? 1 : 0]);
- }
+ glEnable(GL_BLEND);
- widget_draw_vertex_buffer(pos, col, GL_TRIANGLE_FAN, wtb->inner_v, col_array, wtb->totvert);
- immUnbindProgram();
+ /* backdrop non AA */
+ if (wtb->draw_inner) {
+ if (wcol->shaded == 0) {
+ /* simple fill */
+ inner_col1[0] = inner_col2[0] = (unsigned char)wcol->inner[0];
+ inner_col1[1] = inner_col2[1] = (unsigned char)wcol->inner[1];
+ inner_col1[2] = inner_col2[2] = (unsigned char)wcol->inner[2];
+ inner_col1[3] = inner_col2[3] = (unsigned char)wcol->inner[3];
+ }
+ else {
+ /* gradient fill */
+ shadecolors4((char *)inner_col1, (char *)inner_col2, wcol->inner, wcol->shadetop, wcol->shadedown);
}
}
- /* for each AA step */
if (wtb->draw_outline) {
- BLI_assert(wtb->totvert != 0);
- float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
- float triangle_strip_emboss[WIDGET_SIZE_MAX * 2][2]; /* only for emboss */
-
- const unsigned char tcol[4] = {wcol->outline[0],
- wcol->outline[1],
- wcol->outline[2],
- wcol->outline[3] / WIDGET_AA_JITTER};
- unsigned char emboss[4];
-
- widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip);
+ outline_col[0] = wcol->outline[0];
+ outline_col[1] = wcol->outline[1];
+ outline_col[2] = wcol->outline[2];
+ outline_col[3] = wcol->outline[3] / WIDGET_AA_JITTER;
+ /* emboss bottom shadow */
if (wtb->draw_emboss) {
- widget_verts_to_triangle_strip_open(wtb, wtb->halfwayvert, triangle_strip_emboss);
- UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss);
+ UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss_col);
}
+ }
- unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- for (j = 0; j < WIDGET_AA_JITTER; j++) {
- gpuTranslate2fv(jit[j]);
-
- /* outline */
- immUniformColor4ubv(tcol);
+ if (wtb->tria1.type != ROUNDBOX_TRIA_NONE)
+ {
+ tria_col[0] = wcol->item[0];
+ tria_col[1] = wcol->item[1];
+ tria_col[2] = wcol->item[2];
+ tria_col[3] = (unsigned char)((float)wcol->item[3] / WIDGET_AA_JITTER);
+ }
- widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2);
+ /* Draw everything in one drawcall */
+ if (inner_col1[3] || inner_col2[3] || outline_col[3] || emboss_col[3] || tria_col[3] || alpha_check) {
+ widgetbase_set_uniform_colors_ubv(wtb, inner_col1, inner_col2, outline_col, emboss_col, tria_col, alpha_check);
- /* emboss bottom shadow */
- if (wtb->draw_emboss) {
- if (emboss[3]) {
- immUniformColor4ubv(emboss);
- widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip_emboss, NULL, wtb->halfwayvert * 2);
- }
- }
-
- gpuTranslate2f(-jit[j][0], -jit[j][1]);
- }
- immUnbindProgram();
+ Gwn_Batch *roundbox_batch = ui_batch_roundbox_widget_get(wtb->tria1.type);
+ draw_widgetbase_batch(roundbox_batch, wtb);
}
- /* decoration */
- if (wtb->tria1.tot || wtb->tria2.tot) {
+ /* DEPRECATED: should be removed at some point. */
+ if ((wtb->tria1.type == ROUNDBOX_TRIA_NONE) &&
+ (wtb->tria1.tot || wtb->tria2.tot))
+ {
const unsigned char tcol[4] = {wcol->item[0],
wcol->item[1],
wcol->item[2],
@@ -838,17 +1141,14 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
immUniformColor4ubv(tcol);
/* for each AA step */
- for (j = 0; j < WIDGET_AA_JITTER; j++) {
- gpuTranslate2fv(jit[j]);
-
- if (wtb->tria1.tot)
- shape_preset_draw_trias(&wtb->tria1, pos);
-
- if (wtb->tria2.tot)
- shape_preset_draw_trias(&wtb->tria2, pos);
-
- gpuTranslate2f(-jit[j][0], -jit[j][1]);
+ immBegin(GWN_PRIM_TRIS, (wtb->tria1.tot + wtb->tria2.tot) * 3 * WIDGET_AA_JITTER);
+ if (wtb->tria1.tot){
+ shape_preset_draw_trias_aa(&wtb->tria1, pos);
+ }
+ if (wtb->tria2.tot) {
+ shape_preset_draw_trias_aa(&wtb->tria2, pos);
}
+ immEnd();
immUnbindProgram();
}
@@ -1411,6 +1711,10 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
int selsta_draw, selwidth_draw;
if (drawstr[0] != 0) {
+ /* We are drawing on top of widget bases. Flush cache. */
+ glEnable(GL_BLEND);
+ UI_widgetbase_draw_cache_flush();
+ glDisable(GL_BLEND);
if (but->selsta >= but->ofs) {
selsta_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selsta - but->ofs);
@@ -1452,6 +1756,10 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
else {
t = 0;
}
+ /* We are drawing on top of widget bases. Flush cache. */
+ glEnable(GL_BLEND);
+ UI_widgetbase_draw_cache_flush();
+ glDisable(GL_BLEND);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -1591,6 +1899,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
rcti temp = *rect;
temp.xmin = rect->xmax - BLI_rcti_size_y(rect) - 1;
widget_draw_icon(but, ICON_LAYER_USED, alpha, &temp, false);
+ rect->xmax = temp.xmin;
}
/* If there's an icon too (made with uiDefIconTextBut) then draw the icon
@@ -2734,6 +3043,11 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
widgetbase_draw(&wtb, &wcol_tmp);
+ /* We are drawing on top of widget bases. Flush cache. */
+ glEnable(GL_BLEND);
+ UI_widgetbase_draw_cache_flush();
+ glDisable(GL_BLEND);
+
/* cursor */
x = rect->xmin + 0.5f * BLI_rcti_size_x(rect);
y = rect->ymin + v * BLI_rcti_size_y(rect);
@@ -2891,7 +3205,7 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s
else
rad = 0.5f * BLI_rcti_size_x(rect);
- wtb.draw_shadedir = (horizontal) ? true : false;
+ wtb.uniform_params.shade_dir = (horizontal) ? 1.0f : 0.0;
/* draw back part, colors swapped and shading inverted */
if (horizontal)
@@ -3204,7 +3518,6 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
}
widgetbase_draw(&wtb, wcol);
-
if (but->a1 == UI_PALETTE_COLOR && ((Palette *)but->rnapoin.id.data)->active_color == (int)but->a2) {
float width = rect->xmax - rect->xmin;
float height = rect->ymax - rect->ymin;
@@ -3213,6 +3526,11 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
bw += (bw < 0.5f) ? 0.5f : -0.5f;
+ /* We are drawing on top of widget bases. Flush cache. */
+ glEnable(GL_BLEND);
+ UI_widgetbase_draw_cache_flush();
+ glDisable(GL_BLEND);
+
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -3285,6 +3603,8 @@ static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
/* decoration */
shape_preset_trias_from_rect_menu(&wtb.tria1, rect);
+ /* copy size and center to 2nd tria */
+ wtb.tria2 = wtb.tria1;
widgetbase_draw(&wtb, wcol);
@@ -3568,6 +3888,11 @@ static void widget_tab(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(
wtb.draw_outline = 0;
widgetbase_draw(&wtb, wcol);
+ /* We are drawing on top of widget bases. Flush cache. */
+ glEnable(GL_BLEND);
+ UI_widgetbase_draw_cache_flush();
+ glDisable(GL_BLEND);
+
/* draw outline (3d look) */
ui_draw_but_TAB_outline(rect, rad, theme_col_tab_highlight, (unsigned char *)wcol->inner);
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 2eae452debb..687b225b838 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -45,6 +45,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BKE_addon.h"
#include "BKE_appdir.h"
#include "BKE_colorband.h"
#include "BKE_DerivedMesh.h"
@@ -2307,13 +2308,9 @@ void init_userdef_do_versions(void)
if (btheme->tipo.handle_sel_auto_clamped[3] == 0)
rgba_char_args_set(btheme->tipo.handle_sel_auto_clamped, 0xf0, 0xaf, 0x90, 255);
}
-
+
/* enable (Cycles) addon by default */
- if (!BLI_findstring(&U.addons, "cycles", offsetof(bAddon, module))) {
- bAddon *baddon = MEM_callocN(sizeof(bAddon), "bAddon");
- BLI_strncpy(baddon->module, "cycles", sizeof(baddon->module));
- BLI_addtail(&U.addons, baddon);
- }
+ BKE_addon_ensure(&U.addons, "cycles");
}
if (!USER_VERSION_ATLEAST(260, 5)) {
@@ -2974,6 +2971,15 @@ void init_userdef_do_versions(void)
// we default to the first audio device
U.audiodevice = 0;
+ /* Not versioning, just avoid errors. */
+#ifndef WITH_CYCLES
+ bAddon *addon = BLI_findstring(&U.addons, "cycles", offsetof(bAddon, module));
+ if (addon) {
+ BLI_remlink(&U.addons, addon);
+ BKE_addon_free(addon);
+ }
+#endif
+
/* funny name, but it is GE stuff, moves userdef stuff to engine */
// XXX space_set_commmandline_options();
/* this timer uses U */
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index a94ef0d1d5b..375711194a3 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -1027,6 +1027,13 @@ bool UI_view2d_tab_set(View2D *v2d, int tab)
void UI_view2d_zoom_cache_reset(void)
{
+ /* TODO(sergey): This way we avoid threading conflict with VSE rendering
+ * text strip. But ideally we want to make glyph cache to be fully safe
+ * for threading.
+ */
+ if (G.is_rendering) {
+ return;
+ }
/* While scaling we can accumulate fonts at many sizes (~20 or so).
* Not an issue with embedded font, but can use over 500Mb with i18n ones! See [#38244]. */
@@ -1204,10 +1211,10 @@ static void step_to_grid(float *step, int *power, int unit)
* - Units + clamping args will be checked, to make sure they are valid values that can be used
* so it is very possible that we won't return grid at all!
*
- * - xunits,yunits = V2D_UNIT_* grid steps in seconds or frames
- * - xclamp,yclamp = V2D_CLAMP_* only show whole-number intervals
- * - winx = width of region we're drawing to, note: not used but keeping for completeness.
- * - winy = height of region we're drawing into
+ * - xunits,yunits = V2D_UNIT_* grid steps in seconds or frames
+ * - xclamp,yclamp = V2D_CLAMP_* only show whole-number intervals
+ * - winx = width of region we're drawing to, note: not used but keeping for completeness.
+ * - winy = height of region we're drawing into
*/
View2DGrid *UI_view2d_grid_calc(
Scene *scene, View2D *v2d,
@@ -1885,7 +1892,9 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
/* draw numbers in the appropriate range */
if (dfac > 0.0f) {
float h = 0.1f * UI_UNIT_Y + (float)(hor.ymin);
-
+
+ BLF_batch_draw_begin();
+
for (; fac < hor.xmax - 0.5f * U.widget_unit; fac += dfac, val += grid->dx) {
/* make prints look nicer for scrollers */
@@ -1912,6 +1921,8 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
break;
}
}
+
+ BLF_batch_draw_end();
}
}
}
diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c
index ca4ab30a08d..b584782e183 100644
--- a/source/blender/editors/io/io_alembic.c
+++ b/source/blender/editors/io/io_alembic.c
@@ -59,6 +59,8 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "ED_object.h"
+
#include "UI_interface.h"
#include "UI_resources.h"
@@ -543,6 +545,12 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op)
}
}
+ /* Switch out of edit mode to avoid being stuck in it (T54326). */
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit) {
+ ED_object_mode_toggle(C, OB_MODE_EDIT);
+ }
+
bool ok = ABC_import(C, filename, scale, is_sequence, set_frame_range,
sequence_len, offset, validate_meshes,
as_background_job);
diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c
index 975bbddd893..eb79d0bec13 100644
--- a/source/blender/editors/io/io_cache.c
+++ b/source/blender/editors/io/io_cache.c
@@ -33,7 +33,6 @@
#include "BKE_cachefile.h"
#include "BKE_context.h"
-#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index 1b7fd319da0..4d0d59ae42c 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -28,7 +28,7 @@
* \ingroup collada
*/
#ifdef WITH_COLLADA
-#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
#include "BLT_translation.h"
@@ -39,6 +39,7 @@
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_report.h"
+#include "BKE_object.h"
#include "DEG_depsgraph.h"
@@ -92,6 +93,10 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
int include_shapekeys;
int deform_bones_only;
+ int include_animations;
+ int sample_animations;
+ int sampling_rate;
+
int include_material_textures;
int use_texture_copies;
int active_uv_only;
@@ -143,6 +148,11 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
include_children = RNA_boolean_get(op->ptr, "include_children");
include_armatures = RNA_boolean_get(op->ptr, "include_armatures");
include_shapekeys = RNA_boolean_get(op->ptr, "include_shapekeys");
+
+ include_animations = RNA_boolean_get(op->ptr, "include_animations");
+ sample_animations = RNA_boolean_get(op->ptr, "sample_animations");
+ sampling_rate = (sample_animations) ? RNA_int_get(op->ptr, "sampling_rate") : 0;
+
deform_bones_only = RNA_boolean_get(op->ptr, "deform_bones_only");
include_material_textures = RNA_boolean_get(op->ptr, "include_material_textures");
@@ -162,32 +172,42 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
/* get editmode results */
ED_object_editmode_load(CTX_data_edit_object(C));
+ Scene *scene = CTX_data_scene(C);
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ ExportSettings export_settings;
+
+ export_settings.filepath = filepath;
+
+ export_settings.apply_modifiers = apply_modifiers != 0;
+ export_settings.export_mesh_type = export_mesh_type;
+ export_settings.selected = selected != 0;
+ export_settings.include_children = include_children != 0;
+ export_settings.include_armatures = include_armatures != 0;
+ export_settings.include_shapekeys = include_shapekeys != 0;
+ export_settings.deform_bones_only = deform_bones_only != 0;
+ export_settings.include_animations = include_animations;
+ export_settings.sampling_rate = sampling_rate;
+
+ export_settings.active_uv_only = active_uv_only != 0;
+ export_settings.use_texture_copies = use_texture_copies != 0;
+
+ export_settings.triangulate = triangulate != 0;
+ export_settings.use_object_instantiation = use_object_instantiation != 0;
+ export_settings.use_blender_profile = use_blender_profile != 0;
+ export_settings.sort_by_name = sort_by_name != 0;
+ export_settings.export_transformation_type = export_transformation_type;
+ export_settings.open_sim = open_sim != 0;
+ export_settings.limit_precision = limit_precision != 0;
+ export_settings.keep_bind_info = keep_bind_info != 0;
+
+ int includeFilter = OB_REL_NONE;
+ if (export_settings.include_armatures) includeFilter |= OB_REL_MOD_ARMATURE;
+ if (export_settings.include_children) includeFilter |= OB_REL_CHILDREN_RECURSIVE;
export_count = collada_export(&eval_ctx,
- CTX_data_scene(C),
- CTX_data_view_layer(C),
- filepath,
- apply_modifiers,
- export_mesh_type,
- selected,
- include_children,
- include_armatures,
- include_shapekeys,
- deform_bones_only,
-
- active_uv_only,
- include_material_textures,
- use_texture_copies,
-
- triangulate,
- use_object_instantiation,
- use_blender_profile,
- sort_by_name,
- export_transformation_type,
-
- open_sim,
- limit_precision,
- keep_bind_info
+ scene,
+ &export_settings
);
if (export_count == 0) {
@@ -209,6 +229,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
{
uiLayout *box, *row, *col, *split;
+ bool include_animations = RNA_boolean_get(imfptr, "include_animations");
/* Export Options: */
box = uiLayoutBox(layout);
@@ -238,6 +259,16 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
uiItemR(row, imfptr, "include_shapekeys", 0, NULL, ICON_NONE);
uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "include_animations", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ if (include_animations) {
+ uiItemR(row, imfptr, "sample_animations", 0, NULL, ICON_NONE);
+ row = uiLayoutColumn(box, false);
+ uiItemR(row, imfptr, "sampling_rate", 0, NULL, ICON_NONE);
+ uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "sample_animations"));
+ }
+
/* Texture options */
box = uiLayoutBox(layout);
row = uiLayoutRow(box, false);
@@ -260,6 +291,7 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "deform_bones_only", 0, NULL, ICON_NONE);
+
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "open_sim", 0, NULL, ICON_NONE);
@@ -279,7 +311,6 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
uiItemL(split, IFACE_("Transformation Type"), ICON_NONE);
uiItemR(split, imfptr, "export_transformation_type_selection", 0, "", ICON_NONE);
-
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "sort_by_name", 0, NULL, ICON_NONE);
@@ -356,20 +387,29 @@ void WM_OT_collada_export(wmOperatorType *ot)
RNA_def_enum(func, "export_mesh_type_selection", prop_bc_export_mesh_type, 0,
"Resolution", "Modifier resolution for export");
- RNA_def_boolean(func, "selected", 0, "Selection Only",
+ RNA_def_boolean(func, "selected", false, "Selection Only",
"Export only selected elements");
- RNA_def_boolean(func, "include_children", 0, "Include Children",
+ RNA_def_boolean(func, "include_children", false, "Include Children",
"Export all children of selected objects (even if not selected)");
- RNA_def_boolean(func, "include_armatures", 0, "Include Armatures",
+ RNA_def_boolean(func, "include_armatures", false, "Include Armatures",
"Export related armatures (even if not selected)");
- RNA_def_boolean(func, "include_shapekeys", 1, "Include Shape Keys",
+ RNA_def_boolean(func, "include_shapekeys", false, "Include Shape Keys",
"Export all Shape Keys from Mesh Objects");
- RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only",
- "Only export deforming bones with armatures");
+ RNA_def_boolean(func, "deform_bones_only", false, "Deform Bones only",
+ "Only export deforming bones with armatures");
+
+ RNA_def_boolean(func, "include_animations", true,
+ "Include Animations", "Export Animations if available.\nExporting Animations will enforce the decomposition of node transforms\ninto <translation> <rotation> and <scale> components");
+
+ RNA_def_boolean(func, "sample_animations", 0,
+ "Sample Animations", "Auto-generate keyframes with a frame distance set by 'Sampling Rate'.\nWhen disabled, export only the keyframes defined in the animation f-curves (may be less accurate)");
+
+ RNA_def_int(func, "sampling_rate", 1, 1, INT_MAX,
+ "Sampling Rate", "The distance between 2 keyframes. 1 means: Every frame is keyed", 1, INT_MAX);
RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map",
@@ -423,6 +463,7 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
int min_chain_length;
int keep_bind_info;
+ ImportSettings import_settings;
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
BKE_report(op->reports, RPT_ERROR, "No filename given");
@@ -440,15 +481,16 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
min_chain_length = RNA_int_get(op->ptr, "min_chain_length");
RNA_string_get(op->ptr, "filepath", filename);
- if (collada_import(
- C, filename,
- import_units,
- find_chains,
- auto_connect,
- fix_orientation,
- min_chain_length,
- keep_bind_info) )
- {
+
+ import_settings.filepath = filename;
+ import_settings.import_units = import_units != 0;
+ import_settings.auto_connect = auto_connect != 0;
+ import_settings.find_chains = find_chains != 0;
+ import_settings.fix_orientation = fix_orientation != 0;
+ import_settings.min_chain_length = min_chain_length;
+ import_settings.keep_bind_info = keep_bind_info != 0;
+
+ if (collada_import(C, &import_settings)) {
DEG_id_tag_update(&CTX_data_scene(C)->id, DEG_TAG_BASE_FLAGS_UPDATE);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/lattice/CMakeLists.txt b/source/blender/editors/lattice/CMakeLists.txt
new file mode 100644
index 00000000000..eaf837cf978
--- /dev/null
+++ b/source/blender/editors/lattice/CMakeLists.txt
@@ -0,0 +1,46 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../depsgraph
+ ../../makesdna
+ ../../makesrna
+ ../../render/extern/include
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+)
+
+set(INC_SYS
+
+)
+
+set(SRC
+ editlattice_select.c
+ editlattice_tools.c
+ editlattice_undo.c
+ lattice_ops.c
+
+ lattice_intern.h
+)
+
+blender_add_lib(bf_editor_lattice "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/lattice/editlattice_select.c
index b2f9bee27ff..d0d64b85195 100644
--- a/source/blender/editors/object/object_lattice.c
+++ b/source/blender/editors/lattice/editlattice_select.c
@@ -23,14 +23,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/editors/object/object_lattice.c
- * \ingroup edobj
+/** \file blender/editors/lattice/editlattice_select.c
+ * \ingroup edlattice
*/
-
#include <stdlib.h>
-#include <string.h>
-#include <math.h>
#include "MEM_guardedalloc.h"
@@ -41,7 +38,6 @@
#include "BLI_bitmap.h"
#include "DNA_curve_types.h"
-#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -52,127 +48,21 @@
#include "RNA_enum_types.h"
#include "BKE_context.h"
-#include "BKE_key.h"
#include "BKE_lattice.h"
-#include "BKE_deform.h"
#include "BKE_report.h"
-#include "DEG_depsgraph.h"
-
-#include "ED_lattice.h"
-#include "ED_object.h"
#include "ED_screen.h"
+#include "ED_lattice.h"
#include "ED_view3d.h"
-#include "ED_util.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "object_intern.h"
-
-/********************** Load/Make/Free ********************/
-
-void ED_lattice_editlatt_free(Object *ob)
-{
- Lattice *lt = ob->data;
-
- if (lt->editlatt) {
- Lattice *editlt = lt->editlatt->latt;
-
- if (editlt->def)
- MEM_freeN(editlt->def);
- if (editlt->dvert)
- BKE_defvert_array_free(editlt->dvert, editlt->pntsu * editlt->pntsv * editlt->pntsw);
-
- MEM_freeN(editlt);
- MEM_freeN(lt->editlatt);
-
- lt->editlatt = NULL;
- }
-}
-
-void ED_lattice_editlatt_make(Object *obedit)
-{
- Lattice *lt = obedit->data;
- KeyBlock *actkey;
-
- ED_lattice_editlatt_free(obedit);
-
- actkey = BKE_keyblock_from_object(obedit);
- if (actkey)
- BKE_keyblock_convert_to_lattice(actkey, lt);
-
- lt->editlatt = MEM_callocN(sizeof(EditLatt), "editlatt");
- lt->editlatt->latt = MEM_dupallocN(lt);
- lt->editlatt->latt->def = MEM_dupallocN(lt->def);
-
- if (lt->dvert) {
- int tot = lt->pntsu * lt->pntsv * lt->pntsw;
- lt->editlatt->latt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
- BKE_defvert_array_copy(lt->editlatt->latt->dvert, lt->dvert, tot);
- }
-
- if (lt->key) lt->editlatt->shapenr = obedit->shapenr;
-}
-
-void ED_lattice_editlatt_load(Object *obedit)
-{
- Lattice *lt, *editlt;
- KeyBlock *actkey;
- BPoint *bp;
- float *fp;
- int tot;
-
- lt = obedit->data;
- editlt = lt->editlatt->latt;
-
- if (lt->editlatt->shapenr) {
- actkey = BLI_findlink(&lt->key->block, lt->editlatt->shapenr - 1);
-
- /* active key: vertices */
- tot = editlt->pntsu * editlt->pntsv * editlt->pntsw;
-
- if (actkey->data) MEM_freeN(actkey->data);
-
- fp = actkey->data = MEM_callocN(lt->key->elemsize * tot, "actkey->data");
- actkey->totelem = tot;
-
- bp = editlt->def;
- while (tot--) {
- copy_v3_v3(fp, bp->vec);
- fp += 3;
- bp++;
- }
- }
- else {
- MEM_freeN(lt->def);
-
- lt->def = MEM_dupallocN(editlt->def);
-
- lt->flag = editlt->flag;
-
- lt->pntsu = editlt->pntsu;
- lt->pntsv = editlt->pntsv;
- lt->pntsw = editlt->pntsw;
-
- lt->typeu = editlt->typeu;
- lt->typev = editlt->typev;
- lt->typew = editlt->typew;
- lt->actbp = editlt->actbp;
- }
-
- if (lt->dvert) {
- BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
- lt->dvert = NULL;
- }
+#include "lattice_intern.h"
- if (editlt->dvert) {
- tot = lt->pntsu * lt->pntsv * lt->pntsw;
-
- lt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
- BKE_defvert_array_copy(lt->dvert, editlt->dvert, tot);
- }
-}
+/* -------------------------------------------------------------------- */
+/** \name Utility Functions
+ * \{ */
static void bpoint_select_set(BPoint *bp, bool select)
{
@@ -186,7 +76,11 @@ static void bpoint_select_set(BPoint *bp, bool select)
}
}
-/************************** Select Random Operator **********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Random Operator
+ * \{ */
static int lattice_select_random_exec(bContext *C, wmOperator *op)
{
@@ -242,9 +136,11 @@ void LATTICE_OT_select_random(wmOperatorType *ot)
WM_operator_properties_select_random(ot);
}
+/** \} */
/* -------------------------------------------------------------------- */
-/* Select Mirror Operator */
+/** \name Select Mirror Operator
+ * \{ */
static void ed_lattice_select_mirrored(Lattice *lt, const int axis, const bool extend)
{
@@ -323,8 +219,11 @@ void LATTICE_OT_select_mirror(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
+/** \} */
-/************************** Select More/Less Operator *************************/
+/* -------------------------------------------------------------------- */
+/** \name Select More/Less Operator
+ * \{ */
static bool lattice_test_bitmap_uvw(Lattice *lt, BLI_bitmap *selpoints, int u, int v, int w, const bool selected)
{
@@ -423,16 +322,20 @@ void LATTICE_OT_select_less(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/************************** Select All Operator *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select All Operator
+ * \{ */
void ED_lattice_flags_set(Object *obedit, int flag)
{
Lattice *lt = obedit->data;
BPoint *bp;
int a;
-
+
bp = lt->editlatt->latt->def;
-
+
a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
lt->editlatt->latt->actbp = LT_ACTBP_NONE;
@@ -501,18 +404,22 @@ void LATTICE_OT_select_all(wmOperatorType *ot)
ot->name = "(De)select All";
ot->description = "Change selection of all UVW control points";
ot->idname = "LATTICE_OT_select_all";
-
+
/* api callbacks */
ot->exec = lattice_select_all_exec;
ot->poll = ED_operator_editlattice;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
WM_operator_properties_select_all(ot);
}
-/************************** Select Ungrouped Verts Operator *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Ungrouped Verts Operator
+ * \{ */
static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op)
{
@@ -564,291 +471,22 @@ void LATTICE_OT_select_ungrouped(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
-/************************** Make Regular Operator *************************/
-
-static int make_regular_poll(bContext *C)
-{
- Object *ob;
-
- if (ED_operator_editlattice(C)) return 1;
-
- ob = CTX_data_active_object(C);
- return (ob && ob->type == OB_LATTICE);
-}
-
-static int make_regular_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = CTX_data_edit_object(C);
- Lattice *lt;
-
- if (ob) {
- lt = ob->data;
- BKE_lattice_resize(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
- }
- else {
- ob = CTX_data_active_object(C);
- lt = ob->data;
- BKE_lattice_resize(lt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
- }
-
- DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
-
- return OPERATOR_FINISHED;
-}
-
-void LATTICE_OT_make_regular(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Make Regular";
- ot->description = "Set UVW control points a uniform distance apart";
- ot->idname = "LATTICE_OT_make_regular";
-
- /* api callbacks */
- ot->exec = make_regular_exec;
- ot->poll = make_regular_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/************************** Flip Verts Operator *************************/
-
-/* flipping options */
-typedef enum eLattice_FlipAxes {
- LATTICE_FLIP_U = 0,
- LATTICE_FLIP_V = 1,
- LATTICE_FLIP_W = 2
-} eLattice_FlipAxes;
-
-/* Flip midpoint value so that relative distances between midpoint and neighbor-pair is maintained
- * ! Assumes that uvw <=> xyz (i.e. axis-aligned index-axes with coordinate-axes)
- * - Helper for lattice_flip_exec()
- */
-static void lattice_flip_point_value(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
-{
- BPoint *bp;
- float diff;
-
- /* just the point in the middle (unpaired) */
- bp = &lt->def[BKE_lattice_index_from_uvw(lt, u, v, w)];
-
- /* flip over axis */
- diff = mid - bp->vec[axis];
- bp->vec[axis] = mid + diff;
-}
+/** \} */
-/* Swap pairs of lattice points along a specified axis
- * - Helper for lattice_flip_exec()
- */
-static void lattice_swap_point_pairs(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
-{
- BPoint *bpA, *bpB;
-
- int numU = lt->pntsu;
- int numV = lt->pntsv;
- int numW = lt->pntsw;
-
- int u0 = u, u1 = u;
- int v0 = v, v1 = v;
- int w0 = w, w1 = w;
-
- /* get pair index by just overriding the relevant pair-value
- * - "-1" else buffer overflow
- */
- switch (axis) {
- case LATTICE_FLIP_U:
- u1 = numU - u - 1;
- break;
- case LATTICE_FLIP_V:
- v1 = numV - v - 1;
- break;
- case LATTICE_FLIP_W:
- w1 = numW - w - 1;
- break;
- }
-
- /* get points to operate on */
- bpA = &lt->def[BKE_lattice_index_from_uvw(lt, u0, v0, w0)];
- bpB = &lt->def[BKE_lattice_index_from_uvw(lt, u1, v1, w1)];
-
- /* Swap all coordinates, so that flipped coordinates belong to
- * the indices on the correct side of the lattice.
- *
- * Coords: (-2 4) |0| (3 4) --> (3 4) |0| (-2 4)
- * Indices: (0,L) (1,R) --> (0,L) (1,R)
- */
- swap_v3_v3(bpA->vec, bpB->vec);
-
- /* However, we need to mirror the coordinate values on the axis we're dealing with,
- * otherwise we'd have effectively only rotated the points around. If we don't do this,
- * we'd just be reimplementing the naive mirroring algorithm, which causes unwanted deforms
- * such as flipped normals, etc.
- *
- * Coords: (3 4) |0| (-2 4) --\
- * \-> (-3 4) |0| (2 4)
- * Indices: (0,L) (1,R) --> (0,L) (1,R)
- */
- lattice_flip_point_value(lt, u0, v0, w0, mid, axis);
- lattice_flip_point_value(lt, u1, v1, w1, mid, axis);
-}
-
-static int lattice_flip_exec(bContext *C, wmOperator *op)
-{
- Object *obedit = CTX_data_edit_object(C);
- Lattice *lt;
-
- eLattice_FlipAxes axis = RNA_enum_get(op->ptr, "axis");
- int numU, numV, numW;
- int totP;
-
- float mid = 0.0f;
- short isOdd = 0;
-
- /* get lattice - we need the "edit lattice" from the lattice... confusing... */
- lt = (Lattice *)obedit->data;
- lt = lt->editlatt->latt;
-
- numU = lt->pntsu;
- numV = lt->pntsv;
- numW = lt->pntsw;
- totP = numU * numV * numW;
-
- /* First Pass: determine midpoint - used for flipping center verts if there are odd number of points on axis */
- switch (axis) {
- case LATTICE_FLIP_U:
- isOdd = numU & 1;
- break;
- case LATTICE_FLIP_V:
- isOdd = numV & 1;
- break;
- case LATTICE_FLIP_W:
- isOdd = numW & 1;
- break;
-
- default:
- printf("lattice_flip(): Unknown flipping axis (%u)\n", axis);
- return OPERATOR_CANCELLED;
- }
-
- if (isOdd) {
- BPoint *bp;
- float avgInv = 1.0f / (float)totP;
- int i;
-
- /* midpoint calculation - assuming that u/v/w are axis-aligned */
- for (i = 0, bp = lt->def; i < totP; i++, bp++) {
- mid += bp->vec[axis] * avgInv;
- }
- }
-
- /* Second Pass: swap pairs of vertices per axis, assuming they are all sorted */
- switch (axis) {
- case LATTICE_FLIP_U:
- {
- int u, v, w;
-
- /* v/w strips - front to back, top to bottom */
- for (w = 0; w < numW; w++) {
- for (v = 0; v < numV; v++) {
- /* swap coordinates of pairs of vertices on u */
- for (u = 0; u < (numU / 2); u++) {
- lattice_swap_point_pairs(lt, u, v, w, mid, axis);
- }
-
- /* flip u-coordinate of midpoint (i.e. unpaired point on u) */
- if (isOdd) {
- u = (numU / 2);
- lattice_flip_point_value(lt, u, v, w, mid, axis);
- }
- }
- }
- break;
- }
- case LATTICE_FLIP_V:
- {
- int u, v, w;
-
- /* u/w strips - front to back, left to right */
- for (w = 0; w < numW; w++) {
- for (u = 0; u < numU; u++) {
- /* swap coordinates of pairs of vertices on v */
- for (v = 0; v < (numV / 2); v++) {
- lattice_swap_point_pairs(lt, u, v, w, mid, axis);
- }
-
- /* flip v-coordinate of midpoint (i.e. unpaired point on v) */
- if (isOdd) {
- v = (numV / 2);
- lattice_flip_point_value(lt, u, v, w, mid, axis);
- }
- }
- }
- break;
- }
- case LATTICE_FLIP_W:
- {
- int u, v, w;
-
- for (v = 0; v < numV; v++) {
- for (u = 0; u < numU; u++) {
- /* swap coordinates of pairs of vertices on w */
- for (w = 0; w < (numW / 2); w++) {
- lattice_swap_point_pairs(lt, u, v, w, mid, axis);
- }
-
- /* flip w-coordinate of midpoint (i.e. unpaired point on w) */
- if (isOdd) {
- w = (numW / 2);
- lattice_flip_point_value(lt, u, v, w, mid, axis);
- }
- }
- }
- break;
- }
- default: /* shouldn't happen, but just in case */
- break;
- }
-
- /* updates */
- DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-void LATTICE_OT_flip(wmOperatorType *ot)
-{
- static const EnumPropertyItem flip_items[] = {
- {LATTICE_FLIP_U, "U", 0, "U (X) Axis", ""},
- {LATTICE_FLIP_V, "V", 0, "V (Y) Axis", ""},
- {LATTICE_FLIP_W, "W", 0, "W (Z) Axis", ""},
- {0, NULL, 0, NULL, NULL}};
-
- /* identifiers */
- ot->name = "Flip (Distortion Free)";
- ot->description = "Mirror all control points without inverting the lattice deform";
- ot->idname = "LATTICE_OT_flip";
-
- /* api callbacks */
- ot->poll = ED_operator_editlattice;
- ot->invoke = WM_menu_invoke;
- ot->exec = lattice_flip_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "axis", flip_items, LATTICE_FLIP_U, "Flip Axis", "Coordinates along this axis get flipped");
-}
+/* -------------------------------------------------------------------- */
+/** \name Select Picking API
+ *
+ * Here actual select happens,
+ * Gets called via generic mouse select operator.
+ * \{ */
-/****************************** Mouse Selection *************************/
static void findnearestLattvert__doClosest(void *userData, BPoint *bp, const float screen_co[2])
{
struct { BPoint *bp; float dist; int select; float mval_fl[2]; } *data = userData;
float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
-
+
if ((bp->f1 & SELECT) && data->select)
dist_test += 5.0f;
@@ -883,7 +521,7 @@ bool ED_lattice_select_pick(bContext *C, const int mval[2], bool extend, bool de
BPoint *bp = NULL;
Lattice *lt;
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
lt = ((Lattice *)vc.obedit->data)->editlatt->latt;
bp = findnearestLattvert(&vc, mval, true);
@@ -917,70 +555,4 @@ bool ED_lattice_select_pick(bContext *C, const int mval[2], bool extend, bool de
return false;
}
-/******************************** Undo *************************/
-
-typedef struct UndoLattice {
- BPoint *def;
- int pntsu, pntsv, pntsw, actbp;
-} UndoLattice;
-
-static void undoLatt_to_editLatt(void *data, void *edata, void *UNUSED(obdata))
-{
- UndoLattice *ult = (UndoLattice *)data;
- EditLatt *editlatt = (EditLatt *)edata;
- int a = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw;
-
- memcpy(editlatt->latt->def, ult->def, a * sizeof(BPoint));
- editlatt->latt->actbp = ult->actbp;
-}
-
-static void *editLatt_to_undoLatt(void *edata, void *UNUSED(obdata))
-{
- UndoLattice *ult = MEM_callocN(sizeof(UndoLattice), "UndoLattice");
- EditLatt *editlatt = (EditLatt *)edata;
-
- ult->def = MEM_dupallocN(editlatt->latt->def);
- ult->pntsu = editlatt->latt->pntsu;
- ult->pntsv = editlatt->latt->pntsv;
- ult->pntsw = editlatt->latt->pntsw;
- ult->actbp = editlatt->latt->actbp;
-
- return ult;
-}
-
-static void free_undoLatt(void *data)
-{
- UndoLattice *ult = (UndoLattice *)data;
-
- if (ult->def) MEM_freeN(ult->def);
- MEM_freeN(ult);
-}
-
-static int validate_undoLatt(void *data, void *edata)
-{
- UndoLattice *ult = (UndoLattice *)data;
- EditLatt *editlatt = (EditLatt *)edata;
-
- return (ult->pntsu == editlatt->latt->pntsu &&
- ult->pntsv == editlatt->latt->pntsv &&
- ult->pntsw == editlatt->latt->pntsw);
-}
-
-static void *get_editlatt(bContext *C)
-{
- Object *obedit = CTX_data_edit_object(C);
-
- if (obedit && obedit->type == OB_LATTICE) {
- Lattice *lt = obedit->data;
- return lt->editlatt;
- }
-
- return NULL;
-}
-
-/* and this is all the undo system needs to know */
-void undo_push_lattice(bContext *C, const char *name)
-{
- undo_editmode_push(C, name, get_editlatt, free_undoLatt, undoLatt_to_editLatt, editLatt_to_undoLatt, validate_undoLatt);
-}
-
+/** \} */
diff --git a/source/blender/editors/lattice/editlattice_tools.c b/source/blender/editors/lattice/editlattice_tools.c
new file mode 100644
index 00000000000..bf60c1e7da6
--- /dev/null
+++ b/source/blender/editors/lattice/editlattice_tools.c
@@ -0,0 +1,341 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/lattice/editlattice_tools.c
+ * \ingroup edlattice
+ */
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "BKE_context.h"
+#include "BKE_lattice.h"
+
+#include "DEG_depsgraph.h"
+
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "lattice_intern.h"
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Make Regular Operator
+ * \{ */
+
+static int make_regular_poll(bContext *C)
+{
+ Object *ob;
+
+ if (ED_operator_editlattice(C)) return 1;
+
+ ob = CTX_data_active_object(C);
+ return (ob && ob->type == OB_LATTICE);
+}
+
+static int make_regular_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = CTX_data_edit_object(C);
+ Lattice *lt;
+
+ if (ob) {
+ lt = ob->data;
+ BKE_lattice_resize(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
+ }
+ else {
+ ob = CTX_data_active_object(C);
+ lt = ob->data;
+ BKE_lattice_resize(lt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
+ }
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void LATTICE_OT_make_regular(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Make Regular";
+ ot->description = "Set UVW control points a uniform distance apart";
+ ot->idname = "LATTICE_OT_make_regular";
+
+ /* api callbacks */
+ ot->exec = make_regular_exec;
+ ot->poll = make_regular_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Flip Verts Operator
+ * \{ */
+
+/* flipping options */
+typedef enum eLattice_FlipAxes {
+ LATTICE_FLIP_U = 0,
+ LATTICE_FLIP_V = 1,
+ LATTICE_FLIP_W = 2
+} eLattice_FlipAxes;
+
+/**
+ * Flip midpoint value so that relative distances between midpoint and neighbor-pair is maintained
+ * ! Assumes that uvw <=> xyz (i.e. axis-aligned index-axes with coordinate-axes)
+ * - Helper for lattice_flip_exec()
+ */
+static void lattice_flip_point_value(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
+{
+ BPoint *bp;
+ float diff;
+
+ /* just the point in the middle (unpaired) */
+ bp = &lt->def[BKE_lattice_index_from_uvw(lt, u, v, w)];
+
+ /* flip over axis */
+ diff = mid - bp->vec[axis];
+ bp->vec[axis] = mid + diff;
+}
+
+/**
+ * Swap pairs of lattice points along a specified axis
+ * - Helper for lattice_flip_exec()
+ */
+static void lattice_swap_point_pairs(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
+{
+ BPoint *bpA, *bpB;
+
+ int numU = lt->pntsu;
+ int numV = lt->pntsv;
+ int numW = lt->pntsw;
+
+ int u0 = u, u1 = u;
+ int v0 = v, v1 = v;
+ int w0 = w, w1 = w;
+
+ /* get pair index by just overriding the relevant pair-value
+ * - "-1" else buffer overflow
+ */
+ switch (axis) {
+ case LATTICE_FLIP_U:
+ u1 = numU - u - 1;
+ break;
+ case LATTICE_FLIP_V:
+ v1 = numV - v - 1;
+ break;
+ case LATTICE_FLIP_W:
+ w1 = numW - w - 1;
+ break;
+ }
+
+ /* get points to operate on */
+ bpA = &lt->def[BKE_lattice_index_from_uvw(lt, u0, v0, w0)];
+ bpB = &lt->def[BKE_lattice_index_from_uvw(lt, u1, v1, w1)];
+
+ /* Swap all coordinates, so that flipped coordinates belong to
+ * the indices on the correct side of the lattice.
+ *
+ * Coords: (-2 4) |0| (3 4) --> (3 4) |0| (-2 4)
+ * Indices: (0,L) (1,R) --> (0,L) (1,R)
+ */
+ swap_v3_v3(bpA->vec, bpB->vec);
+
+ /* However, we need to mirror the coordinate values on the axis we're dealing with,
+ * otherwise we'd have effectively only rotated the points around. If we don't do this,
+ * we'd just be reimplementing the naive mirroring algorithm, which causes unwanted deforms
+ * such as flipped normals, etc.
+ *
+ * Coords: (3 4) |0| (-2 4) --\
+ * \-> (-3 4) |0| (2 4)
+ * Indices: (0,L) (1,R) --> (0,L) (1,R)
+ */
+ lattice_flip_point_value(lt, u0, v0, w0, mid, axis);
+ lattice_flip_point_value(lt, u1, v1, w1, mid, axis);
+}
+
+static int lattice_flip_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Lattice *lt;
+
+ eLattice_FlipAxes axis = RNA_enum_get(op->ptr, "axis");
+ int numU, numV, numW;
+ int totP;
+
+ float mid = 0.0f;
+ short isOdd = 0;
+
+ /* get lattice - we need the "edit lattice" from the lattice... confusing... */
+ lt = (Lattice *)obedit->data;
+ lt = lt->editlatt->latt;
+
+ numU = lt->pntsu;
+ numV = lt->pntsv;
+ numW = lt->pntsw;
+ totP = numU * numV * numW;
+
+ /* First Pass: determine midpoint - used for flipping center verts if there are odd number of points on axis */
+ switch (axis) {
+ case LATTICE_FLIP_U:
+ isOdd = numU & 1;
+ break;
+ case LATTICE_FLIP_V:
+ isOdd = numV & 1;
+ break;
+ case LATTICE_FLIP_W:
+ isOdd = numW & 1;
+ break;
+
+ default:
+ printf("lattice_flip(): Unknown flipping axis (%u)\n", axis);
+ return OPERATOR_CANCELLED;
+ }
+
+ if (isOdd) {
+ BPoint *bp;
+ float avgInv = 1.0f / (float)totP;
+ int i;
+
+ /* midpoint calculation - assuming that u/v/w are axis-aligned */
+ for (i = 0, bp = lt->def; i < totP; i++, bp++) {
+ mid += bp->vec[axis] * avgInv;
+ }
+ }
+
+ /* Second Pass: swap pairs of vertices per axis, assuming they are all sorted */
+ switch (axis) {
+ case LATTICE_FLIP_U:
+ {
+ int u, v, w;
+
+ /* v/w strips - front to back, top to bottom */
+ for (w = 0; w < numW; w++) {
+ for (v = 0; v < numV; v++) {
+ /* swap coordinates of pairs of vertices on u */
+ for (u = 0; u < (numU / 2); u++) {
+ lattice_swap_point_pairs(lt, u, v, w, mid, axis);
+ }
+
+ /* flip u-coordinate of midpoint (i.e. unpaired point on u) */
+ if (isOdd) {
+ u = (numU / 2);
+ lattice_flip_point_value(lt, u, v, w, mid, axis);
+ }
+ }
+ }
+ break;
+ }
+ case LATTICE_FLIP_V:
+ {
+ int u, v, w;
+
+ /* u/w strips - front to back, left to right */
+ for (w = 0; w < numW; w++) {
+ for (u = 0; u < numU; u++) {
+ /* swap coordinates of pairs of vertices on v */
+ for (v = 0; v < (numV / 2); v++) {
+ lattice_swap_point_pairs(lt, u, v, w, mid, axis);
+ }
+
+ /* flip v-coordinate of midpoint (i.e. unpaired point on v) */
+ if (isOdd) {
+ v = (numV / 2);
+ lattice_flip_point_value(lt, u, v, w, mid, axis);
+ }
+ }
+ }
+ break;
+ }
+ case LATTICE_FLIP_W:
+ {
+ int u, v, w;
+
+ for (v = 0; v < numV; v++) {
+ for (u = 0; u < numU; u++) {
+ /* swap coordinates of pairs of vertices on w */
+ for (w = 0; w < (numW / 2); w++) {
+ lattice_swap_point_pairs(lt, u, v, w, mid, axis);
+ }
+
+ /* flip w-coordinate of midpoint (i.e. unpaired point on w) */
+ if (isOdd) {
+ w = (numW / 2);
+ lattice_flip_point_value(lt, u, v, w, mid, axis);
+ }
+ }
+ }
+ break;
+ }
+ default: /* shouldn't happen, but just in case */
+ break;
+ }
+
+ /* updates */
+ DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void LATTICE_OT_flip(wmOperatorType *ot)
+{
+ static const EnumPropertyItem flip_items[] = {
+ {LATTICE_FLIP_U, "U", 0, "U (X) Axis", ""},
+ {LATTICE_FLIP_V, "V", 0, "V (Y) Axis", ""},
+ {LATTICE_FLIP_W, "W", 0, "W (Z) Axis", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+ /* identifiers */
+ ot->name = "Flip (Distortion Free)";
+ ot->description = "Mirror all control points without inverting the lattice deform";
+ ot->idname = "LATTICE_OT_flip";
+
+ /* api callbacks */
+ ot->poll = ED_operator_editlattice;
+ ot->invoke = WM_menu_invoke;
+ ot->exec = lattice_flip_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "axis", flip_items, LATTICE_FLIP_U, "Flip Axis", "Coordinates along this axis get flipped");
+}
+
+/** \} */
diff --git a/source/blender/editors/lattice/editlattice_undo.c b/source/blender/editors/lattice/editlattice_undo.c
new file mode 100644
index 00000000000..58fa08e5aa9
--- /dev/null
+++ b/source/blender/editors/lattice/editlattice_undo.c
@@ -0,0 +1,196 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/lattice/editlattice_undo.c
+ * \ingroup edlattice
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_array_utils.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_context.h"
+#include "BKE_undo_system.h"
+
+#include "DEG_depsgraph.h"
+
+#include "ED_object.h"
+#include "ED_lattice.h"
+#include "ED_util.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+#include "lattice_intern.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Undo Conversion
+ * \{ */
+
+typedef struct UndoLattice {
+ BPoint *def;
+ int pntsu, pntsv, pntsw, actbp;
+ size_t undo_size;
+} UndoLattice;
+
+static void undolatt_to_editlatt(UndoLattice *ult, EditLatt *editlatt)
+{
+ int len = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw;
+
+ memcpy(editlatt->latt->def, ult->def, sizeof(BPoint) * len);
+ editlatt->latt->actbp = ult->actbp;
+}
+
+static void *undolatt_from_editlatt(UndoLattice *ult, EditLatt *editlatt)
+{
+ BLI_assert(BLI_array_is_zeroed(ult, 1));
+
+ ult->def = MEM_dupallocN(editlatt->latt->def);
+ ult->pntsu = editlatt->latt->pntsu;
+ ult->pntsv = editlatt->latt->pntsv;
+ ult->pntsw = editlatt->latt->pntsw;
+ ult->actbp = editlatt->latt->actbp;
+
+ ult->undo_size += sizeof(*ult->def) * ult->pntsu * ult->pntsv * ult->pntsw;
+
+ return ult;
+}
+
+static void undolatt_free_data(UndoLattice *ult)
+{
+ if (ult->def) {
+ MEM_freeN(ult->def);
+ }
+}
+
+#if 0
+static int validate_undoLatt(void *data, void *edata)
+{
+ UndoLattice *ult = (UndoLattice *)data;
+ EditLatt *editlatt = (EditLatt *)edata;
+
+ return (ult->pntsu == editlatt->latt->pntsu &&
+ ult->pntsv == editlatt->latt->pntsv &&
+ ult->pntsw == editlatt->latt->pntsw);
+}
+#endif
+
+static Object *editlatt_object_from_context(bContext *C)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_LATTICE) {
+ Lattice *lt = obedit->data;
+ if (lt->editlatt != NULL) {
+ return obedit;
+ }
+ }
+
+ return NULL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Implements ED Undo System
+ * \{ */
+
+typedef struct LatticeUndoStep {
+ UndoStep step;
+ /* note: will split out into list for multi-object-editmode. */
+ UndoRefID_Object obedit_ref;
+ UndoLattice data;
+} LatticeUndoStep;
+
+static bool lattice_undosys_poll(bContext *C)
+{
+ return editlatt_object_from_context(C) != NULL;
+}
+
+static bool lattice_undosys_step_encode(struct bContext *C, UndoStep *us_p)
+{
+ LatticeUndoStep *us = (LatticeUndoStep *)us_p;
+ us->obedit_ref.ptr = editlatt_object_from_context(C);
+ Lattice *lt = us->obedit_ref.ptr->data;
+ undolatt_from_editlatt(&us->data, lt->editlatt);
+ us->step.data_size = us->data.undo_size;
+ return true;
+}
+
+static void lattice_undosys_step_decode(struct bContext *C, UndoStep *us_p, int UNUSED(dir))
+{
+ /* TODO(campbell): undo_system: use low-level API to set mode. */
+ ED_object_mode_set(C, OB_MODE_EDIT);
+ BLI_assert(lattice_undosys_poll(C));
+
+ LatticeUndoStep *us = (LatticeUndoStep *)us_p;
+ Object *obedit = us->obedit_ref.ptr;
+ Lattice *lt = obedit->data;
+ EditLatt *editlatt = lt->editlatt;
+ undolatt_to_editlatt(&us->data, editlatt);
+ DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+}
+
+static void lattice_undosys_step_free(UndoStep *us_p)
+{
+ LatticeUndoStep *us = (LatticeUndoStep *)us_p;
+ undolatt_free_data(&us->data);
+}
+
+static void lattice_undosys_foreach_ID_ref(
+ UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+{
+ LatticeUndoStep *us = (LatticeUndoStep *)us_p;
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->obedit_ref));
+}
+
+/* Export for ED_undo_sys. */
+void ED_lattice_undosys_type(UndoType *ut)
+{
+ ut->name = "Edit Lattice";
+ ut->poll = lattice_undosys_poll;
+ ut->step_encode = lattice_undosys_step_encode;
+ ut->step_decode = lattice_undosys_step_decode;
+ ut->step_free = lattice_undosys_step_free;
+
+ ut->step_foreach_ID_ref = lattice_undosys_foreach_ID_ref;
+
+ ut->mode = BKE_UNDOTYPE_MODE_STORE;
+ ut->use_context = true;
+
+ ut->step_size = sizeof(LatticeUndoStep);
+}
+
+/** \} */
diff --git a/source/blender/editors/lattice/lattice_intern.h b/source/blender/editors/lattice/lattice_intern.h
new file mode 100644
index 00000000000..7902b992270
--- /dev/null
+++ b/source/blender/editors/lattice/lattice_intern.h
@@ -0,0 +1,44 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/lattice/lattice_intern.h
+ * \ingroup edlattice
+ */
+
+
+#ifndef __LATTICE_INTERN_H__
+#define __LATTICE_INTERN_H__
+
+/* editlattice_select.c */
+void LATTICE_OT_select_all(struct wmOperatorType *ot);
+void LATTICE_OT_select_more(struct wmOperatorType *ot);
+void LATTICE_OT_select_less(struct wmOperatorType *ot);
+void LATTICE_OT_select_ungrouped(struct wmOperatorType *ot);
+void LATTICE_OT_select_random(struct wmOperatorType *ot);
+void LATTICE_OT_select_mirror(struct wmOperatorType *ot);
+
+/* editlattice_tools.c */
+void LATTICE_OT_make_regular(struct wmOperatorType *ot);
+void LATTICE_OT_flip(struct wmOperatorType *ot);
+
+#endif /* __LATTICE_INTERN_H__ */
diff --git a/source/blender/editors/lattice/lattice_ops.c b/source/blender/editors/lattice/lattice_ops.c
new file mode 100644
index 00000000000..d3d57a0b510
--- /dev/null
+++ b/source/blender/editors/lattice/lattice_ops.c
@@ -0,0 +1,80 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/lattice/lattice_ops.c
+ * \ingroup edlattice
+ */
+
+#include "DNA_scene_types.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_object.h"
+#include "ED_lattice.h"
+
+#include "lattice_intern.h"
+
+void ED_operatortypes_lattice(void)
+{
+ WM_operatortype_append(LATTICE_OT_select_all);
+ WM_operatortype_append(LATTICE_OT_select_more);
+ WM_operatortype_append(LATTICE_OT_select_less);
+ WM_operatortype_append(LATTICE_OT_select_ungrouped);
+ WM_operatortype_append(LATTICE_OT_select_random);
+ WM_operatortype_append(LATTICE_OT_select_mirror);
+ WM_operatortype_append(LATTICE_OT_make_regular);
+ WM_operatortype_append(LATTICE_OT_flip);
+}
+
+void ED_keymap_lattice(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap;
+ wmKeyMapItem *kmi;
+
+ keymap = WM_keymap_find(keyconf, "Lattice", 0, 0);
+ keymap->poll = ED_operator_editlattice;
+
+ kmi = WM_keymap_add_item(keymap, "LATTICE_OT_select_all", AKEY, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE);
+ kmi = WM_keymap_add_item(keymap, "LATTICE_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "action", SEL_INVERT);
+ WM_keymap_add_item(keymap, "LATTICE_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "LATTICE_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "OBJECT_OT_vertex_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "LATTICE_OT_flip", FKEY, KM_PRESS, KM_CTRL, 0);
+
+ /* menus */
+ WM_keymap_add_menu(keymap, "VIEW3D_MT_hook", HKEY, KM_PRESS, KM_CTRL, 0);
+
+ ED_keymap_proportional_cycle(keyconf, keymap);
+ ED_keymap_proportional_editmode(keyconf, keymap, false);
+}
diff --git a/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c
index 0299a33d0fe..23c6030f091 100644
--- a/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c
+++ b/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c
@@ -37,7 +37,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
-#include "BLI_dial.h"
+#include "BLI_dial_2d.h"
#include "BLI_rect.h"
#include "BKE_context.h"
diff --git a/source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c
index d58cdb4b187..67fb2419931 100644
--- a/source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c
+++ b/source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c
@@ -37,7 +37,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
-#include "BLI_dial.h"
+#include "BLI_dial_2d.h"
#include "BLI_rect.h"
#include "BKE_context.h"
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index c60b673ec69..689a96a3dec 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -555,7 +555,7 @@ static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, c
const int width, const int height)
{
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
GPU_enable_program_point_size();
MaskLayer *masklay;
diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c
index 9f2f6de8a09..7ffd82e262c 100644
--- a/source/blender/editors/mask/mask_select.c
+++ b/source/blender/editors/mask/mask_select.c
@@ -33,7 +33,7 @@
#include "BLI_utildefines.h"
#include "BLI_rect.h"
-#include "BLI_lasso.h"
+#include "BLI_lasso_2d.h"
#include "BLI_math.h"
#include "BKE_context.h"
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index 80e1187609c..3877838ec54 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -60,6 +60,7 @@ set(SRC
editmesh_undo.c
editmesh_utils.c
mesh_data.c
+ mesh_mirror.c
mesh_ops.c
meshtools.c
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 992d0fada5e..1b9ee70ccf5 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -24,7 +24,6 @@
* \ingroup edmesh
*/
-
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
@@ -41,7 +40,6 @@
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_context.h"
-#include "BKE_editmesh.h"
#include "BIF_gl.h"
@@ -609,258 +607,3 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
paintvert_flush_flags(ob);
}
}
-
-/* ********************* MESH VERTEX MIRR TOPO LOOKUP *************** */
-/* note, this is not the best place for the function to be but moved
- * here for the purpose of syncing with bmesh */
-
-typedef unsigned int MirrTopoHash_t;
-
-typedef struct MirrTopoVert_t {
- MirrTopoHash_t hash;
- int v_index;
-} MirrTopoVert_t;
-
-static int mirrtopo_hash_sort(const void *l1, const void *l2)
-{
- if ((MirrTopoHash_t)(intptr_t)l1 > (MirrTopoHash_t)(intptr_t)l2) return 1;
- else if ((MirrTopoHash_t)(intptr_t)l1 < (MirrTopoHash_t)(intptr_t)l2) return -1;
- return 0;
-}
-
-static int mirrtopo_vert_sort(const void *v1, const void *v2)
-{
- if (((MirrTopoVert_t *)v1)->hash > ((MirrTopoVert_t *)v2)->hash) return 1;
- else if (((MirrTopoVert_t *)v1)->hash < ((MirrTopoVert_t *)v2)->hash) return -1;
- return 0;
-}
-
-bool ED_mesh_mirrtopo_recalc_check(Mesh *me, DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store)
-{
- int totvert;
- int totedge;
-
- if (dm) {
- totvert = dm->getNumVerts(dm);
- totedge = dm->getNumEdges(dm);
- }
- else if (me->edit_btmesh) {
- totvert = me->edit_btmesh->bm->totvert;
- totedge = me->edit_btmesh->bm->totedge;
- }
- else {
- totvert = me->totvert;
- totedge = me->totedge;
- }
-
- if ((mesh_topo_store->index_lookup == NULL) ||
- (mesh_topo_store->prev_ob_mode != ob_mode) ||
- (totvert != mesh_topo_store->prev_vert_tot) ||
- (totedge != mesh_topo_store->prev_edge_tot))
- {
- return true;
- }
- else {
- return false;
- }
-
-}
-
-void ED_mesh_mirrtopo_init(Mesh *me, DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
- const bool skip_em_vert_array_init)
-{
- MEdge *medge = NULL, *med;
- BMEditMesh *em = dm ? NULL : me->edit_btmesh;
-
- /* editmode*/
- BMEdge *eed;
- BMIter iter;
-
- int a, last;
- int totvert, totedge;
- int tot_unique = -1, tot_unique_prev = -1;
- int tot_unique_edges = 0, tot_unique_edges_prev;
-
- MirrTopoHash_t *topo_hash = NULL;
- MirrTopoHash_t *topo_hash_prev = NULL;
- MirrTopoVert_t *topo_pairs;
- MirrTopoHash_t topo_pass = 1;
-
- intptr_t *index_lookup; /* direct access to mesh_topo_store->index_lookup */
-
- /* reallocate if needed */
- ED_mesh_mirrtopo_free(mesh_topo_store);
-
- mesh_topo_store->prev_ob_mode = ob_mode;
-
- if (em) {
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
-
- totvert = em->bm->totvert;
- }
- else {
- totvert = dm ? dm->getNumVerts(dm) : me->totvert;
- }
-
- topo_hash = MEM_callocN(totvert * sizeof(MirrTopoHash_t), "TopoMirr");
-
- /* Initialize the vert-edge-user counts used to detect unique topology */
- if (em) {
- totedge = me->edit_btmesh->bm->totedge;
-
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- const int i1 = BM_elem_index_get(eed->v1), i2 = BM_elem_index_get(eed->v2);
- topo_hash[i1]++;
- topo_hash[i2]++;
- }
- }
- else {
- totedge = dm ? dm->getNumEdges(dm) : me->totedge;
- medge = dm ? dm->getEdgeArray(dm) : me->medge;
-
- for (a = 0, med = medge; a < totedge; a++, med++) {
- const unsigned int i1 = med->v1, i2 = med->v2;
- topo_hash[i1]++;
- topo_hash[i2]++;
- }
- }
-
- topo_hash_prev = MEM_dupallocN(topo_hash);
-
- tot_unique_prev = -1;
- tot_unique_edges_prev = -1;
- while (1) {
- /* use the number of edges per vert to give verts unique topology IDs */
-
- tot_unique_edges = 0;
-
- /* This can make really big numbers, wrapping around here is fine */
- if (em) {
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- const int i1 = BM_elem_index_get(eed->v1), i2 = BM_elem_index_get(eed->v2);
- topo_hash[i1] += topo_hash_prev[i2] * topo_pass;
- topo_hash[i2] += topo_hash_prev[i1] * topo_pass;
- tot_unique_edges += (topo_hash[i1] != topo_hash[i2]);
- }
- }
- else {
- for (a = 0, med = medge; a < totedge; a++, med++) {
- const unsigned int i1 = med->v1, i2 = med->v2;
- topo_hash[i1] += topo_hash_prev[i2] * topo_pass;
- topo_hash[i2] += topo_hash_prev[i1] * topo_pass;
- tot_unique_edges += (topo_hash[i1] != topo_hash[i2]);
- }
- }
- memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert);
-
- /* sort so we can count unique values */
- qsort(topo_hash_prev, totvert, sizeof(MirrTopoHash_t), mirrtopo_hash_sort);
-
- tot_unique = 1; /* account for skiping the first value */
- for (a = 1; a < totvert; a++) {
- if (topo_hash_prev[a - 1] != topo_hash_prev[a]) {
- tot_unique++;
- }
- }
-
- if ((tot_unique <= tot_unique_prev) && (tot_unique_edges <= tot_unique_edges_prev)) {
- /* Finish searching for unique values when 1 loop dosnt give a
- * higher number of unique values compared to the previous loop */
- break;
- }
- else {
- tot_unique_prev = tot_unique;
- tot_unique_edges_prev = tot_unique_edges;
- }
- /* Copy the hash calculated this iter, so we can use them next time */
- memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert);
-
- topo_pass++;
- }
-
- /* Hash/Index pairs are needed for sorting to find index pairs */
- topo_pairs = MEM_callocN(sizeof(MirrTopoVert_t) * totvert, "MirrTopoPairs");
-
- /* since we are looping through verts, initialize these values here too */
- index_lookup = MEM_mallocN(totvert * sizeof(*index_lookup), "mesh_topo_lookup");
-
- if (em) {
- if (skip_em_vert_array_init == false) {
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- }
- }
-
- for (a = 0; a < totvert; a++) {
- topo_pairs[a].hash = topo_hash[a];
- topo_pairs[a].v_index = a;
-
- /* initialize lookup */
- index_lookup[a] = -1;
- }
-
- qsort(topo_pairs, totvert, sizeof(MirrTopoVert_t), mirrtopo_vert_sort);
-
- last = 0;
-
- /* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2,
- * but you cant ever access the last 'a' index of MirrTopoPairs */
- if (em) {
- BMVert **vtable = em->bm->vtable;
- for (a = 1; a <= totvert; a++) {
- /* printf("I %d %ld %d\n", (a - last), MirrTopoPairs[a].hash, MirrTopoPairs[a].v_indexs); */
- if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) {
- const int match_count = a - last;
- if (match_count == 2) {
- const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index;
- index_lookup[j] = (intptr_t)vtable[k];
- index_lookup[k] = (intptr_t)vtable[j];
- }
- else if (match_count == 1) {
- /* Center vertex. */
- const int j = topo_pairs[a - 1].v_index;
- index_lookup[j] = (intptr_t)vtable[j];
- }
- last = a;
- }
- }
- }
- else {
- /* same as above, for mesh */
- for (a = 1; a <= totvert; a++) {
- if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) {
- const int match_count = a - last;
- if (match_count == 2) {
- const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index;
- index_lookup[j] = k;
- index_lookup[k] = j;
- }
- else if (match_count == 1) {
- /* Center vertex. */
- const int j = topo_pairs[a - 1].v_index;
- index_lookup[j] = j;
- }
- last = a;
- }
- }
- }
-
- MEM_freeN(topo_pairs);
- topo_pairs = NULL;
-
- MEM_freeN(topo_hash);
- MEM_freeN(topo_hash_prev);
-
- mesh_topo_store->index_lookup = index_lookup;
- mesh_topo_store->prev_vert_tot = totvert;
- mesh_topo_store->prev_edge_tot = totedge;
-}
-
-void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store)
-{
- if (mesh_topo_store->index_lookup) {
- MEM_freeN(mesh_topo_store->index_lookup);
- }
- mesh_topo_store->index_lookup = NULL;
- mesh_topo_store->prev_vert_tot = -1;
- mesh_topo_store->prev_edge_tot = -1;
-}
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index a21fc2fffde..292b28c772c 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -65,9 +65,10 @@ typedef struct MakePrimitiveData {
bool was_editmode;
} MakePrimitiveData;
-static Object *make_prim_init(bContext *C, const char *idname,
- const float loc[3], const float rot[3], const unsigned int layer,
- MakePrimitiveData *r_creation_data)
+static Object *make_prim_init(
+ bContext *C, const char *idname,
+ const float loc[3], const float rot[3], const unsigned int layer,
+ MakePrimitiveData *r_creation_data)
{
Object *obedit = CTX_data_edit_object(C);
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index d4d7d92d5ad..c8d33a9cc60 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -139,6 +139,10 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
return false;
}
+ if (is_modal) {
+ RNA_float_set(op->ptr, "offset", 0.0f);
+ }
+
op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator");
opdata->em = em;
@@ -622,7 +626,6 @@ void MESH_OT_bevel(wmOperatorType *ot)
RNA_def_enum(ot->srna, "offset_type", offset_type_items, 0, "Amount Type", "What distance Amount measures");
prop = RNA_def_float(ot->srna, "offset", 0.0f, -1e6f, 1e6f, "Amount", "", 0.0f, 1.0f);
RNA_def_property_float_array_funcs_runtime(prop, NULL, NULL, mesh_ot_bevel_offset_range_func);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
RNA_def_int(ot->srna, "segments", 1, 1, SEGMENTS_HARD_MAX, "Segments", "Segments for curved edge", 1, 8);
RNA_def_float(ot->srna, "profile", 0.5f, PROFILE_HARD_MIN, 1.0f, "Profile",
"Controls profile shape (0.5 = round)", PROFILE_HARD_MIN, 1.0f);
diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c
index 1937a9f6891..741d16206cd 100644
--- a/source/blender/editors/mesh/editmesh_bisect.c
+++ b/source/blender/editors/mesh/editmesh_bisect.c
@@ -58,7 +58,7 @@
#ifdef USE_MANIPULATOR
#include "ED_manipulator_library.h"
-#include "ED_util.h"
+#include "ED_undo.h"
#endif
static int mesh_bisect_exec(bContext *C, wmOperator *op);
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index 18320ec65f5..41b3ab0079b 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -36,8 +36,6 @@
#include "BLI_listbase.h"
#include "BKE_context.h"
-#include "BKE_global.h"
-#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_editmesh.h"
@@ -63,9 +61,13 @@
#ifdef USE_MANIPULATOR
#include "ED_manipulator_library.h"
-#include "ED_util.h"
+#include "ED_undo.h"
#endif
+/* -------------------------------------------------------------------- */
+/** \name Extrude Internal Utilities
+ * \{ */
+
static void edbm_extrude_edge_exclude_mirror(
Object *obedit, BMEditMesh *em,
const char hflag,
@@ -154,7 +156,7 @@ static bool edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const ch
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
BMO_op_exec(em->bm, &bmop);
-
+
BMO_ITER (f, &siter, bmop.slots_out, "faces.out", BM_FACE) {
BM_face_select_set(em->bm, f, true);
@@ -254,7 +256,7 @@ static bool edbm_extrude_ex(
BMOIter siter;
BMOperator extop;
BMElem *ele;
-
+
/* needed to remove the faces left behind */
if (htype & BM_FACE) {
htype |= BM_EDGE;
@@ -276,7 +278,7 @@ static bool edbm_extrude_ex(
BM_SELECT_HISTORY_RESTORE(bm);
BMO_op_exec(bm, &extop);
-
+
BMO_ITER (ele, &siter, extop.slots_out, "geom.out", BM_ALL_NOLOOP) {
BM_elem_select_set(bm, ele, true);
}
@@ -286,14 +288,20 @@ static bool edbm_extrude_ex(
return true;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Extrude Repeat Operator
+ * \{ */
+
static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
-
+
const int steps = RNA_int_get(op->ptr, "steps");
-
+
const float offs = RNA_float_get(op->ptr, "offset");
float dvec[3], tmat[3][3], bmat[3][3];
short a;
@@ -314,7 +322,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
"translate vec=%v verts=%hv",
dvec, BM_ELEM_SELECT);
}
-
+
EDBM_mesh_normals_update(em);
EDBM_update_generic(em, true, true);
@@ -328,19 +336,25 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot)
ot->name = "Extrude Repeat Mesh";
ot->description = "Extrude selected vertices, edges or faces repeatedly";
ot->idname = "MESH_OT_extrude_repeat";
-
+
/* api callbacks */
ot->exec = edbm_extrude_repeat_exec;
ot->poll = ED_operator_editmesh_view3d;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
RNA_def_float_distance(ot->srna, "offset", 2.0f, 0.0f, 1e12f, "Offset", "", 0.0f, 100.0f);
RNA_def_int(ot->srna, "steps", 10, 0, 1000000, "Steps", "", 0, 180);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Extrude Operator
+ * \{ */
+
/* generic extern called extruder */
static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op)
{
@@ -377,7 +391,7 @@ static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op)
changed = edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT);
break;
}
-
+
if (changed) {
return true;
}
@@ -392,7 +406,7 @@ static int edbm_extrude_region_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
+
edbm_extrude_mesh(obedit, em, op);
/* This normally happens when pushing undo but modal operators
@@ -401,7 +415,7 @@ static int edbm_extrude_region_exec(bContext *C, wmOperator *op)
EDBM_mesh_normals_update(em);
EDBM_update_generic(em, true, true);
-
+
return OPERATOR_FINISHED;
}
@@ -411,27 +425,33 @@ void MESH_OT_extrude_region(wmOperatorType *ot)
ot->name = "Extrude Region";
ot->idname = "MESH_OT_extrude_region";
ot->description = "Extrude region of faces";
-
+
/* api callbacks */
//ot->invoke = mesh_extrude_region_invoke;
ot->exec = edbm_extrude_region_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Extrude Verts Operator
+ * \{ */
+
static int edbm_extrude_verts_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT);
-
+
EDBM_update_generic(em, true, true);
-
+
return OPERATOR_FINISHED;
}
@@ -441,11 +461,11 @@ void MESH_OT_extrude_verts_indiv(wmOperatorType *ot)
ot->name = "Extrude Only Vertices";
ot->idname = "MESH_OT_extrude_verts_indiv";
ot->description = "Extrude individual vertices only";
-
+
/* api callbacks */
ot->exec = edbm_extrude_verts_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -453,15 +473,21 @@ void MESH_OT_extrude_verts_indiv(wmOperatorType *ot)
Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Extrude Edges Operator
+ * \{ */
+
static int edbm_extrude_edges_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT);
-
+
EDBM_update_generic(em, true, true);
-
+
return OPERATOR_FINISHED;
}
@@ -471,11 +497,11 @@ void MESH_OT_extrude_edges_indiv(wmOperatorType *ot)
ot->name = "Extrude Only Edges";
ot->idname = "MESH_OT_extrude_edges_indiv";
ot->description = "Extrude individual edges only";
-
+
/* api callbacks */
ot->exec = edbm_extrude_edges_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -483,15 +509,21 @@ void MESH_OT_extrude_edges_indiv(wmOperatorType *ot)
Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Extrude Faces Operator
+ * \{ */
+
static int edbm_extrude_faces_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
edbm_extrude_discrete_faces(em, op, BM_ELEM_SELECT);
-
+
EDBM_update_generic(em, true, true);
-
+
return OPERATOR_FINISHED;
}
@@ -501,18 +533,25 @@ void MESH_OT_extrude_faces_indiv(wmOperatorType *ot)
ot->name = "Extrude Individual Faces";
ot->idname = "MESH_OT_extrude_faces_indiv";
ot->description = "Extrude individual faces only";
-
+
/* api callbacks */
ot->exec = edbm_extrude_faces_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
}
-/* *************** add-click-mesh (extrude) operator ************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Dupli-Extrude Operator
+ *
+ * Add-click-mesh (extrude) operator.
+ * \{ */
+
static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewContext vc;
@@ -533,7 +572,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
zero_v3(center);
verts_len = 0;
-
+
BM_ITER_MESH (v1, &iter, vc.em->bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v1, BM_ELEM_SELECT)) {
add_v3_v3(center, v1->co);
@@ -596,7 +635,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
cross_v3_v3v3(nor, view_vec, cross);
normalize_v3(nor);
}
-
+
/* center */
copy_v3_v3(ofs, center);
@@ -605,7 +644,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
mul_m4_v3(vc.obedit->imat, ofs); // back in object space
sub_v3_v3(ofs, center);
-
+
/* calculate rotation */
unit_m3(mat);
if (done) {
@@ -628,7 +667,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
axis_angle_to_mat3(mat, axis, angle);
}
}
-
+
if (rot_src) {
EDBM_op_callf(vc.em, op, "rotate verts=%hv cent=%v matrix=%m3",
BM_ELEM_SELECT, center, mat);
@@ -653,7 +692,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center);
mul_m4_v3(vc.obedit->imat, center); // back in object space
-
+
EDBM_op_init(vc.em, &bmop, op, "create_vert co=%v", center);
BMO_op_exec(vc.em->bm, &bmop);
@@ -685,17 +724,22 @@ void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot)
ot->name = "Duplicate or Extrude to Cursor";
ot->idname = "MESH_OT_dupli_extrude_cursor";
ot->description = "Duplicate and extrude selected vertices, edges or faces towards the mouse cursor";
-
+
/* api callbacks */
ot->invoke = edbm_dupli_extrude_cursor_invoke;
ot->poll = ED_operator_editmesh_region_view3d;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "rotate_source", true, "Rotate Source", "Rotate initial selection giving better shape");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Spin Operator
+ * \{ */
static int edbm_spin_exec(bContext *C, wmOperator *op)
{
@@ -815,8 +859,7 @@ void MESH_OT_spin(wmOperatorType *ot)
#ifdef USE_MANIPULATOR
/* -------------------------------------------------------------------- */
-
-/** \name Spin Manipulator
+/** \name Screw Operator
* \{ */
typedef struct ManipulatorSpinGroup {
@@ -1315,3 +1358,5 @@ void MESH_OT_screw(wmOperatorType *ot)
RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f,
"Axis", "Axis in global view space", -1.0f, 1.0f);
}
+
+/** \} */
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index 6fd4203e085..3833b84b5d2 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -122,6 +122,11 @@ static bool edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal)
return false;
}
+ if (is_modal) {
+ RNA_float_set(op->ptr, "thickness", 0.01f);
+ RNA_float_set(op->ptr, "depth", 0.0f);
+ }
+
op->customdata = opdata = MEM_mallocN(sizeof(InsetData), "inset_operator_data");
opdata->old_thickness = 0.01;
@@ -527,11 +532,9 @@ void MESH_OT_inset(wmOperatorType *ot)
prop = RNA_def_float_distance(ot->srna, "thickness", 0.01f, 0.0f, 1e12f, "Thickness", "", 0.0f, 10.0f);
/* use 1 rather then 10 for max else dragging the button moves too far */
RNA_def_property_ui_range(prop, 0.0, 1.0, 0.01, 4);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_float_distance(ot->srna, "depth", 0.0f, -1e12f, 1e12f, "Depth", "", -10.0f, 10.0f);
RNA_def_property_ui_range(prop, -10.0f, 10.0f, 0.01, 4);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
RNA_def_boolean(ot->srna, "use_outset", false, "Outset", "Outset rather than inset");
RNA_def_boolean(ot->srna, "use_select_inset", false, "Select Outer", "Select the new inset faces");
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index 3498c6246d7..d681d904e74 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -400,7 +400,7 @@ static void bm_face_split_by_edges(
bm, f, edge_net_temp_buf->data, edge_net_temp_buf->count,
&face_arr, &face_arr_len);
- BLI_buffer_empty(edge_net_temp_buf);
+ BLI_buffer_clear(edge_net_temp_buf);
if (face_arr_len) {
int i;
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 5d5e54edf56..0a12291c128 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -860,7 +860,7 @@ static void knife_cut_face(KnifeTool_OpData *kcd, BMFace *f, ListBase *hits)
{
Ref *r;
- if (BLI_listbase_count_ex(hits, 2) != 2)
+ if (BLI_listbase_count_at_most(hits, 2) != 2)
return;
for (r = hits->first; r->next; r = r->next) {
@@ -1116,7 +1116,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
int i;
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
/* draw any snapped verts first */
immUniformColor4ubv(kcd->colors.point_a);
@@ -1158,7 +1158,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
immUniformColor3ubv(kcd->colors.line);
glLineWidth(1.0);
- immBeginAtMost(GWN_PRIM_LINES, BLI_mempool_count(kcd->kedges) * 2);
+ immBeginAtMost(GWN_PRIM_LINES, BLI_mempool_len(kcd->kedges) * 2);
BLI_mempool_iternew(kcd->kedges, &iter);
for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) {
@@ -1179,7 +1179,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
immUniformColor3ubv(kcd->colors.point);
glPointSize(5.0);
- immBeginAtMost(GWN_PRIM_POINTS, BLI_mempool_count(kcd->kverts));
+ immBeginAtMost(GWN_PRIM_POINTS, BLI_mempool_len(kcd->kverts));
BLI_mempool_iternew(kcd->kverts, &iter);
for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) {
@@ -1782,7 +1782,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
}
kcd->linehits = linehits;
- kcd->totlinehit = BLI_array_count(linehits);
+ kcd->totlinehit = BLI_array_len(linehits);
/* find position along screen line, used for sorting */
for (i = 0; i < kcd->totlinehit; i++) {
@@ -2300,7 +2300,7 @@ static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfe
/* point to knife edges we've created edges in, edge_array aligned */
KnifeEdge **kfe_array = BLI_array_alloca(kfe_array, edge_array_len);
- BLI_assert(BLI_gset_size(kcd->edgenet.edge_visit) == 0);
+ BLI_assert(BLI_gset_len(kcd->edgenet.edge_visit) == 0);
i = 0;
for (ref = kfedges->first; ref; ref = ref->next) {
diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c
index b71dd029bf2..2ae48bee095 100644
--- a/source/blender/editors/mesh/editmesh_path.c
+++ b/source/blender/editors/mesh/editmesh_path.c
@@ -63,6 +63,10 @@
#include "mesh_intern.h" /* own include */
+/* -------------------------------------------------------------------- */
+/** \name Path Select Struct & Properties
+ * \{ */
+
struct PathSelectParams {
bool track_active; /* ensure the active element is the last selected item (handy for picking) */
bool use_topology_distance;
@@ -102,8 +106,11 @@ struct UserData {
const struct PathSelectParams *op_params;
};
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* Vert Path */
+/** \name Vert Path
+ * \{ */
/* callbacks */
static bool verttag_filter_cb(BMVert *v, void *UNUSED(user_data_v))
@@ -121,10 +128,9 @@ static void verttag_set_cb(BMVert *v, bool val, void *user_data_v)
}
static void mouse_mesh_shortest_path_vert(
- Scene *scene, const struct PathSelectParams *op_params,
+ Scene *UNUSED(scene), Object *obedit, const struct PathSelectParams *op_params,
BMVert *v_act, BMVert *v_dst)
{
- Object *obedit = scene->obedit;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
@@ -206,10 +212,11 @@ static void mouse_mesh_shortest_path_vert(
EDBM_update_generic(em, false, false);
}
-
+/** \} */
/* -------------------------------------------------------------------- */
-/* Edge Path */
+/** \name Edge Path
+ * \{ */
/* callbacks */
static bool edgetag_filter_cb(BMEdge *e, void *UNUSED(user_data_v))
@@ -280,11 +287,11 @@ static void edgetag_set_cb(BMEdge *e, bool val, void *user_data_v)
}
}
-static void edgetag_ensure_cd_flag(Scene *scene, Mesh *me)
+static void edgetag_ensure_cd_flag(Mesh *me, const char edge_mode)
{
BMesh *bm = me->edit_btmesh->bm;
- switch (scene->toolsettings->edge_mode) {
+ switch (edge_mode) {
case EDGE_MODE_TAG_CREASE:
BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE);
break;
@@ -307,10 +314,9 @@ static void edgetag_ensure_cd_flag(Scene *scene, Mesh *me)
/* since you want to create paths with multiple selects, it doesn't have extend option */
static void mouse_mesh_shortest_path_edge(
- Scene *scene, const struct PathSelectParams *op_params,
+ Scene *scene, Object *obedit, const struct PathSelectParams *op_params,
BMEdge *e_act, BMEdge *e_dst)
{
- Object *obedit = scene->obedit;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
@@ -319,7 +325,7 @@ static void mouse_mesh_shortest_path_edge(
Mesh *me = obedit->data;
bool is_path_ordered = false;
- edgetag_ensure_cd_flag(scene, obedit->data);
+ edgetag_ensure_cd_flag(obedit->data, op_params->edge_mode);
if (e_act && (e_act != e_dst)) {
if (op_params->use_fill) {
@@ -377,7 +383,7 @@ static void mouse_mesh_shortest_path_edge(
}
else {
const bool is_act = !edgetag_test_cb(e_dst, &user_data);
- edgetag_ensure_cd_flag(scene, obedit->data);
+ edgetag_ensure_cd_flag(obedit->data, op_params->edge_mode);
edgetag_set_cb(e_dst, is_act, &user_data); /* switch the edge option */
}
@@ -429,10 +435,11 @@ static void mouse_mesh_shortest_path_edge(
EDBM_update_generic(em, false, false);
}
-
+/** \} */
/* -------------------------------------------------------------------- */
-/* Face Path */
+/** \name Face Path
+ * \{ */
/* callbacks */
static bool facetag_filter_cb(BMFace *f, void *UNUSED(user_data_v))
@@ -452,10 +459,9 @@ static void facetag_set_cb(BMFace *f, bool val, void *user_data_v)
}
static void mouse_mesh_shortest_path_face(
- Scene *scene, const struct PathSelectParams *op_params,
+ Scene *UNUSED(scene), Object *obedit, const struct PathSelectParams *op_params,
BMFace *f_act, BMFace *f_dst)
{
- Object *obedit = scene->obedit;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
@@ -480,7 +486,6 @@ static void mouse_mesh_shortest_path_face(
facetag_filter_cb, &user_data);
}
-
if (f_act != f_dst) {
if (path) {
if (op_params->track_active) {
@@ -541,13 +546,14 @@ static void mouse_mesh_shortest_path_face(
EDBM_update_generic(em, false, false);
}
-
+/** \} */
/* -------------------------------------------------------------------- */
-/* Main Operator for vert/edge/face tag */
+/** \name Main Operator for vert/edge/face tag
+ * \{ */
static bool edbm_shortest_path_pick_ex(
- Scene *scene, const struct PathSelectParams *op_params,
+ Scene *scene, Object *obedit, const struct PathSelectParams *op_params,
BMElem *ele_src, BMElem *ele_dst)
{
@@ -555,15 +561,15 @@ static bool edbm_shortest_path_pick_ex(
/* pass */
}
else if (ele_src->head.htype == BM_VERT) {
- mouse_mesh_shortest_path_vert(scene, op_params, (BMVert *)ele_src, (BMVert *)ele_dst);
+ mouse_mesh_shortest_path_vert(scene, obedit, op_params, (BMVert *)ele_src, (BMVert *)ele_dst);
return true;
}
else if (ele_src->head.htype == BM_EDGE) {
- mouse_mesh_shortest_path_edge(scene, op_params, (BMEdge *)ele_src, (BMEdge *)ele_dst);
+ mouse_mesh_shortest_path_edge(scene, obedit, op_params, (BMEdge *)ele_src, (BMEdge *)ele_dst);
return true;
}
else if (ele_src->head.htype == BM_FACE) {
- mouse_mesh_shortest_path_face(scene, op_params, (BMFace *)ele_src, (BMFace *)ele_dst);
+ mouse_mesh_shortest_path_face(scene, obedit, op_params, (BMFace *)ele_src, (BMFace *)ele_dst);
return true;
}
@@ -644,7 +650,7 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE
op_params.track_active = track_active;
op_params.edge_mode = vc.scene->toolsettings->edge_mode;
- if (!edbm_shortest_path_pick_ex(vc.scene, &op_params, ele_src, ele_dst)) {
+ if (!edbm_shortest_path_pick_ex(vc.scene, vc.obedit, &op_params, ele_src, ele_dst)) {
return OPERATOR_PASS_THROUGH;
}
@@ -681,7 +687,7 @@ static int edbm_shortest_path_pick_exec(bContext *C, wmOperator *op)
op_params.track_active = true;
op_params.edge_mode = scene->toolsettings->edge_mode;
- if (!edbm_shortest_path_pick_ex(scene, &op_params, ele_src, ele_dst)) {
+ if (!edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst)) {
return OPERATOR_CANCELLED;
}
@@ -713,15 +719,17 @@ void MESH_OT_shortest_path_pick(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
+/** \} */
/* -------------------------------------------------------------------- */
-/* Select path between existing selection */
+/** \name Select Path Between Existing Selection
+ * \{ */
static int edbm_shortest_path_select_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(ob);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
BMIter iter;
BMEditSelection *ese_src, *ese_dst;
@@ -773,7 +781,7 @@ static int edbm_shortest_path_select_exec(bContext *C, wmOperator *op)
struct PathSelectParams op_params;
path_select_params_from_op(op, &op_params);
- edbm_shortest_path_pick_ex(scene, &op_params, ele_src, ele_dst);
+ edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst);
return OPERATOR_FINISHED;
}
@@ -800,3 +808,5 @@ void MESH_OT_shortest_path_select(wmOperatorType *ot)
/* properties */
path_select_properties(ot);
}
+
+/** \} */
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 3e0afd3095e..87937fd4146 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -75,7 +75,9 @@
/* use bmesh operator flags for a few operators */
#define BMO_ELE_TAG 1
-/* ****************************** MIRROR **************** */
+/* -------------------------------------------------------------------- */
+/** \name Select Mirror
+ * \{ */
void EDBM_select_mirrored(
BMEditMesh *em, const int axis, const bool extend,
@@ -168,21 +170,34 @@ void EDBM_select_mirrored(
*r_totfail = totfail;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \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);
+ 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);
}
}
-/* ****************************** SELECTION ROUTINES **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Back-Buffer OpenGL Selection
+ * \{ */
unsigned int bm_solidoffs = 0, bm_wireoffs = 0, bm_vertoffs = 0; /* set in drawobject.c ... for colorindices */
@@ -203,21 +218,21 @@ bool EDBM_backbuf_border_init(
struct ImBuf *buf;
unsigned int *dr;
int a;
-
+
if (vc->obedit == NULL || !V3D_IS_ZBUF(vc->v3d)) {
return false;
}
-
+
buf = ED_view3d_backbuf_read(eval_ctx, vc, xmin, ymin, xmax, ymax);
if ((buf == NULL) || (bm_vertoffs == 0)) {
return false;
}
dr = buf->rect;
-
+
/* build selection lookup */
selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
-
+
a = (xmax - xmin + 1) * (ymax - ymin + 1);
while (a--) {
if (*dr > 0 && *dr <= bm_vertoffs) {
@@ -267,9 +282,9 @@ static void edbm_mask_lasso_px_cb(int x, int x_end, int y, void *user_data)
/* mcords is a polygon mask
* - grab backbuffer,
- * - draw with black in backbuffer,
+ * - draw with black in backbuffer,
* - grab again and compare
- * returns 'OK'
+ * returns 'OK'
*/
bool EDBM_backbuf_border_mask_init(const struct EvaluationContext *eval_ctx, ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
{
@@ -277,7 +292,7 @@ bool EDBM_backbuf_border_mask_init(const struct EvaluationContext *eval_ctx, Vie
struct ImBuf *buf;
int a;
struct LassoMaskData lasso_mask_data;
-
+
/* method in use for face selecting too */
if (vc->obedit == NULL) {
if (!BKE_paint_select_elem_test(vc->obact)) {
@@ -306,7 +321,7 @@ bool EDBM_backbuf_border_mask_init(const struct EvaluationContext *eval_ctx, Vie
/* build selection lookup */
selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
-
+
a = (xmax - xmin + 1) * (ymax - ymin + 1);
while (a--) {
if (*dr > 0 && *dr <= bm_vertoffs && *dr_mask == true) {
@@ -329,7 +344,7 @@ bool EDBM_backbuf_circle_init(
unsigned int *dr;
short xmin, ymin, xmax, ymax, xc, yc;
int radsq;
-
+
/* method in use for face selecting too */
if (vc->obedit == NULL) {
if (!BKE_paint_select_elem_test(vc->obact)) {
@@ -348,7 +363,7 @@ bool EDBM_backbuf_circle_init(
}
dr = buf->rect;
-
+
/* build selection lookup */
selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
radsq = rads * rads;
@@ -364,12 +379,12 @@ bool EDBM_backbuf_circle_init(
IMB_freeImBuf(buf);
return true;
-
+
}
+/** \} */
/* -------------------------------------------------------------------- */
-
/** \name Find Nearest Vert/Edge/Face
*
* \note Screen-space manhatten distances are used here,
@@ -451,14 +466,14 @@ BMVert *EDBM_vert_find_nearest_ex(
float dist_test;
unsigned int index;
BMVert *eve;
-
+
/* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
ED_view3d_backbuf_validate(eval_ctx, vc);
index = ED_view3d_backbuf_sample_rect(
eval_ctx, vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test);
eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
-
+
if (eve) {
if (dist_test < *r_dist) {
*r_dist = dist_test;
@@ -817,7 +832,7 @@ BMFace *EDBM_face_find_nearest_ex(
index = ED_view3d_backbuf_sample(eval_ctx, vc, vc->mval[0], vc->mval[1]);
efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL;
-
+
if (r_efa_zbuf) {
*r_efa_zbuf = efa;
}
@@ -895,8 +910,8 @@ BMFace *EDBM_face_find_nearest(const struct EvaluationContext *eval_ctx, ViewCon
#undef FIND_NEAR_CYCLE_THRESHOLD_MIN
-/* best distance based on screen coords.
- * use em->selectmode to define how to use
+/* best distance based on screen coords.
+ * use em->selectmode to define how to use
* selected vertices and edges get disadvantage
* return 1 if found one
*/
@@ -914,7 +929,7 @@ static int unified_findnearest(
float dist = dist_init;
BMFace *efa_zbuf = NULL;
BMEdge *eed_zbuf = NULL;
-
+
BMVert *eve = NULL;
BMEdge *eed = NULL;
BMFace *efa = NULL;
@@ -976,8 +991,10 @@ static int unified_findnearest(
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Select Similar (Vert/Edge/Face) Operator
+ * \{ */
-/* **************** SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */
static const EnumPropertyItem prop_similar_compare_types[] = {
{SIM_CMP_EQ, "EQUAL", 0, "Equal", ""},
{SIM_CMP_GT, "GREATER", 0, "Greater", ""},
@@ -1054,7 +1071,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
EDBM_update_generic(em, false, false);
return OPERATOR_FINISHED;
-}
+}
/* ***************************************************** */
@@ -1160,8 +1177,9 @@ static int edbm_select_similar_exec(bContext *C, wmOperator *op)
else return similar_face_select_exec(C, op);
}
-static const EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop),
- bool *r_free)
+static const EnumPropertyItem *select_similar_type_itemf(
+ bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
Object *obedit;
@@ -1213,15 +1231,15 @@ void MESH_OT_select_similar(wmOperatorType *ot)
ot->name = "Select Similar";
ot->idname = "MESH_OT_select_similar";
ot->description = "Select similar vertices, edges or faces by property types";
-
+
/* api callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = edbm_select_similar_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
prop = ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, SIMVERT_NORMAL, "Type", "");
RNA_def_enum_funcs(prop, select_similar_type_itemf);
@@ -1231,9 +1249,11 @@ void MESH_OT_select_similar(wmOperatorType *ot)
RNA_def_float(ot->srna, "threshold", 0.0f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
}
+/** \} */
/* -------------------------------------------------------------------- */
-/* Select Similar Regions */
+/** \name Select Similar Region Operator
+ * \{ */
static int edbm_select_similar_region_exec(bContext *C, wmOperator *op)
{
@@ -1254,9 +1274,10 @@ static int edbm_select_similar_region_exec(bContext *C, wmOperator *op)
}
groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
- group_tot = BM_mesh_calc_face_groups(bm, groups_array, &group_index,
- NULL, NULL,
- BM_ELEM_SELECT, BM_VERT);
+ group_tot = BM_mesh_calc_face_groups(
+ bm, groups_array, &group_index,
+ NULL, NULL,
+ BM_ELEM_SELECT, BM_VERT);
BM_mesh_elem_table_ensure(bm, BM_FACE);
@@ -1297,7 +1318,7 @@ static int edbm_select_similar_region_exec(bContext *C, wmOperator *op)
MEM_freeN(group_index);
if (changed) {
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
else {
BKE_report(op->reports, RPT_WARNING, "No matching face regions found");
@@ -1321,8 +1342,11 @@ void MESH_OT_select_similar_region(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
-/* **************** Mode Select *************** */
+/* -------------------------------------------------------------------- */
+/** \name Select Mode Vert/Edge/Face Operator
+ * \{ */
static int edbm_select_mode_exec(bContext *C, wmOperator *op)
{
@@ -1393,12 +1417,15 @@ void MESH_OT_select_mode(wmOperatorType *ot)
RNA_def_enum(ot->srna, "action", actions_items, 2, "Action", "Selection action to execute");
}
-/* ***************************************************** */
+/** \} */
-/* **************** LOOP SELECTS *************** */
+/* -------------------------------------------------------------------- */
+/** \name Select Loop (Non Modal) Operator
+ * \{ */
-static void walker_select_count(BMEditMesh *em, int walkercode, void *start, const bool select, const bool select_mix,
- int *r_totsel, int *r_totunsel)
+static void walker_select_count(
+ BMEditMesh *em, int walkercode, void *start, const bool select, const bool select_mix,
+ int *r_totsel, int *r_totunsel)
{
BMesh *bm = em->bm;
BMElem *ele;
@@ -1453,7 +1480,7 @@ static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op)
BMEdge **edarray;
int edindex;
const bool is_ring = RNA_boolean_get(op->ptr, "ring");
-
+
BMIter iter;
int totedgesel = 0;
@@ -1462,17 +1489,17 @@ static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op)
totedgesel++;
}
}
-
+
edarray = MEM_mallocN(sizeof(BMEdge *) * totedgesel, "edge array");
edindex = 0;
-
+
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
edarray[edindex] = eed;
edindex++;
}
}
-
+
if (is_ring) {
for (edindex = 0; edindex < totedgesel; edindex += 1) {
eed = edarray[edindex];
@@ -1489,8 +1516,8 @@ static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op)
}
MEM_freeN(edarray);
// if (EM_texFaceCheck())
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
@@ -1501,23 +1528,23 @@ void MESH_OT_loop_multi_select(wmOperatorType *ot)
ot->name = "Multi Select Loops";
ot->idname = "MESH_OT_loop_multi_select";
ot->description = "Select a loop of connected edges by connection type";
-
+
/* api callbacks */
ot->exec = edbm_loop_multiselect_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
RNA_def_boolean(ot->srna, "ring", 0, "Ring", "");
}
-
-/* ***************** MAIN MOUSE SELECTION ************** */
-
+/** \} */
-/* ***************** loop select (non modal) ************** */
+/* -------------------------------------------------------------------- */
+/** \name Select Loop (Cursor Pick) Operator
+ * \{ */
static void mouse_mesh_loop_face(BMEditMesh *em, BMEdge *eed, bool select, bool select_clear)
{
@@ -1572,7 +1599,6 @@ static void mouse_mesh_loop_edge(BMEditMesh *em, BMEdge *eed, bool select, bool
}
}
-
static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, bool ring)
{
EvaluationContext eval_ctx;
@@ -1651,11 +1677,15 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de
/* We can't be sure this has already been set... */
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
- if (ED_view3d_project_float_object(vc.ar, eed->v1->co, v1_co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_object(
+ vc.ar, eed->v1->co, v1_co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
+ {
length_1 = len_squared_v2v2(mvalf, v1_co);
}
- if (ED_view3d_project_float_object(vc.ar, eed->v2->co, v2_co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_object(
+ vc.ar, eed->v2->co, v2_co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
+ {
length_2 = len_squared_v2v2(mvalf, v2_co);
}
#if 0
@@ -1682,7 +1712,9 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de
float co[2], tdist;
BM_face_calc_center_mean(f, cent);
- if (ED_view3d_project_float_object(vc.ar, cent, co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_object(
+ vc.ar, cent, co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
+ {
tdist = len_squared_v2v2(mvalf, co);
if (tdist < best_dist) {
/* printf("Best face: %p (%f)\n", f, tdist);*/
@@ -1699,21 +1731,22 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de
}
}
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
return true;
}
static int edbm_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
-
+
view3d_operator_needs_opengl(C);
-
- if (mouse_mesh_loop(C, event->mval,
- RNA_boolean_get(op->ptr, "extend"),
- RNA_boolean_get(op->ptr, "deselect"),
- RNA_boolean_get(op->ptr, "toggle"),
- RNA_boolean_get(op->ptr, "ring")))
+
+ if (mouse_mesh_loop(
+ C, event->mval,
+ RNA_boolean_get(op->ptr, "extend"),
+ RNA_boolean_get(op->ptr, "deselect"),
+ RNA_boolean_get(op->ptr, "toggle"),
+ RNA_boolean_get(op->ptr, "ring")))
{
return OPERATOR_FINISHED;
}
@@ -1728,14 +1761,14 @@ void MESH_OT_loop_select(wmOperatorType *ot)
ot->name = "Loop Select";
ot->idname = "MESH_OT_loop_select";
ot->description = "Select a loop of connected edges";
-
+
/* api callbacks */
ot->invoke = edbm_select_loop_invoke;
ot->poll = ED_operator_editmesh_region_view3d;
-
+
/* flags */
ot->flag = OPTYPE_UNDO;
-
+
/* properties */
RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "Extend the selection");
RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection");
@@ -1749,11 +1782,11 @@ void MESH_OT_edgering_select(wmOperatorType *ot)
ot->name = "Edge Ring Select";
ot->idname = "MESH_OT_edgering_select";
ot->description = "Select an edge ring";
-
+
/* callbacks */
ot->invoke = edbm_select_loop_invoke;
ot->poll = ED_operator_editmesh_region_view3d;
-
+
/* flags */
ot->flag = OPTYPE_UNDO;
@@ -1763,7 +1796,12 @@ void MESH_OT_edgering_select(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "ring", 1, "Select Ring", "Select ring");
}
-/* ******************** (de)select all operator **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name (De)Select All Operator
+ * \{ */
+
static int edbm_select_all_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -1786,7 +1824,7 @@ static int edbm_select_all_exec(bContext *C, wmOperator *op)
break;
}
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
@@ -1808,13 +1846,19 @@ void MESH_OT_select_all(wmOperatorType *ot)
WM_operator_properties_select_all(ot);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Interior Faces Operator
+ * \{ */
+
static int edbm_faces_select_interior_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
if (EDBM_select_interior_faces(em)) {
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
@@ -1839,10 +1883,15 @@ void MESH_OT_select_interior_faces(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Picking API
+ *
+ * Here actual select happens,
+ * Gets called via generic mouse select operator.
+ * \{ */
-/* ************************************************** */
-/* here actual select happens */
-/* gets called via generic mouse select operator */
bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
EvaluationContext eval_ctx;
@@ -1957,7 +2006,7 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect
const int cd_fmap_offset = CustomData_get_offset(&vc.em->bm->pdata, CD_FACEMAP);
if (cd_fmap_offset != -1) {
int map = *((int *)BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset));
- if ((map < -1) || (map > BLI_listbase_count_ex(&vc.obedit->fmaps, map))) {
+ if ((map < -1) || (map > BLI_listbase_count_at_most(&vc.obedit->fmaps, map))) {
map = -1;
}
map += 1;
@@ -1971,13 +2020,19 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect
}
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
return true;
}
return false;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Mode Utilities
+ * \{ */
+
static void edbm_strip_selections(BMEditMesh *em)
{
BMEditSelection *ese, *nextese;
@@ -2016,11 +2071,11 @@ void EDBM_selectmode_set(BMEditMesh *em)
BMEdge *eed;
BMFace *efa;
BMIter iter;
-
+
em->bm->selectmode = em->selectmode;
edbm_strip_selections(em); /* strip BMEditSelections from em->selected that are not relevant to new mode */
-
+
if (em->bm->totvertsel == 0 &&
em->bm->totedgesel == 0 &&
em->bm->totfacesel == 0)
@@ -2183,8 +2238,9 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s
}
/* user facing function, does notification */
-bool EDBM_selectmode_toggle(bContext *C, const short selectmode_new,
- const int action, const bool use_extend, const bool use_expand)
+bool EDBM_selectmode_toggle(
+ bContext *C, const short selectmode_new,
+ const int action, const bool use_extend, const bool use_expand)
{
ToolSettings *ts = CTX_data_tool_settings(C);
Object *obedit = CTX_data_edit_object(C);
@@ -2280,9 +2336,10 @@ bool EDBM_selectmode_toggle(bContext *C, const short selectmode_new,
*
* \return true if the mode is changed.
*/
-bool EDBM_selectmode_disable(Scene *scene, BMEditMesh *em,
- const short selectmode_disable,
- const short selectmode_fallback)
+bool EDBM_selectmode_disable(
+ Scene *scene, BMEditMesh *em,
+ const short selectmode_disable,
+ const short selectmode_fallback)
{
/* note essential, but switch out of vertex mode since the
* selected regions wont be nicely isolated after flushing */
@@ -2305,6 +2362,12 @@ bool EDBM_selectmode_disable(Scene *scene, BMEditMesh *em,
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Toggle
+ * \{ */
+
void EDBM_deselect_by_material(BMEditMesh *em, const short index, const bool select)
{
BMIter iter;
@@ -2333,7 +2396,7 @@ void EDBM_select_swap(BMEditMesh *em) /* exported for UV */
BMVert *eve;
BMEdge *eed;
BMFace *efa;
-
+
if (em->bm->selectmode & SCE_SELECT_VERTEX) {
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN))
@@ -2356,9 +2419,17 @@ void EDBM_select_swap(BMEditMesh *em) /* exported for UV */
}
}
-// if (EM_texFaceCheck())
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Interior Faces
+ *
+ * \note This algorithm is limited to single faces and could be improved, see:
+ * https://blender.stackexchange.com/questions/18916
+ * \{ */
+
bool EDBM_select_interior_faces(BMEditMesh *em)
{
BMesh *bm = em->bm;
@@ -2391,8 +2462,13 @@ bool EDBM_select_interior_faces(BMEditMesh *em)
return changed;
}
+/** \} */
-/************************ Select Linked Operator *************************/
+/* -------------------------------------------------------------------- */
+/** \name Select Linked Operator
+ *
+ * Support delimiting on different edge properties.
+ * \{ */
/* so we can have last-used default depend on selection mode (rare exception!) */
#define USE_LINKED_SELECT_DEFAULT_HACK
@@ -2452,10 +2528,10 @@ static bool select_linked_delimit_test(
* Gets the default from the operator fallback to own last-used value
* (selected based on mode)
*/
-static int select_linked_delimit_default_from_op(wmOperator *op, BMEditMesh *em)
+static int select_linked_delimit_default_from_op(wmOperator *op, int select_mode)
{
static char delimit_last_store[2] = {0, BMO_DELIM_SEAM};
- int delimit_last_index = (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0;
+ int delimit_last_index = (select_mode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0;
char *delimit_last = &delimit_last_store[delimit_last_index];
PropertyRNA *prop_delimit = RNA_struct_find_property(op->ptr, "delimit");
int delimit;
@@ -2525,7 +2601,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
BMWalker walker;
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
- int delimit = select_linked_delimit_default_from_op(op, em);
+ int delimit = select_linked_delimit_default_from_op(op, em->selectmode);
#else
int delimit = RNA_enum_get(op->ptr, "delimit");
#endif
@@ -2683,7 +2759,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
select_linked_delimit_end(em);
}
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
@@ -2713,6 +2789,12 @@ void MESH_OT_select_linked(wmOperatorType *ot)
#endif
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Linked (Cursor Pick) Operator
+ * \{ */
+
static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op);
static void edbm_select_linked_pick_ex(BMEditMesh *em, BMElem *ele, bool sel, int delimit)
@@ -2853,13 +2935,13 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE
/* return warning! */
if (unified_findnearest(&eval_ctx, &vc, &eve, &eed, &efa) == 0) {
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_CANCELLED;
}
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
- int delimit = select_linked_delimit_default_from_op(op, em);
+ int delimit = select_linked_delimit_default_from_op(op, em->selectmode);
#else
int delimit = RNA_enum_get(op->ptr, "delimit");
#endif
@@ -2874,7 +2956,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE
RNA_int_set(op->ptr, "index", index);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
@@ -2896,14 +2978,14 @@ static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op)
BMElem *ele = EDBM_elem_from_index_any(em, index);
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
- int delimit = select_linked_delimit_default_from_op(op, em);
+ int delimit = select_linked_delimit_default_from_op(op, em->selectmode);
#else
int delimit = RNA_enum_get(op->ptr, "delimit");
#endif
edbm_select_linked_pick_ex(em, ele, sel, delimit);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
@@ -2916,15 +2998,15 @@ void MESH_OT_select_linked_pick(wmOperatorType *ot)
ot->name = "Select Linked";
ot->idname = "MESH_OT_select_linked_pick";
ot->description = "(De)select all vertices linked to the edge under the mouse cursor";
-
+
/* api callbacks */
ot->invoke = edbm_select_linked_pick_invoke;
ot->exec = edbm_select_linked_pick_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
prop = RNA_def_enum_flag(ot->srna, "delimit", rna_enum_mesh_delimit_mode_items, BMO_DELIM_SEAM, "Delimit",
"Delimit selected region");
@@ -2937,6 +3019,11 @@ void MESH_OT_select_linked_pick(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Face by Sides Operator
+ * \{ */
static int edbm_select_face_by_sides_exec(bContext *C, wmOperator *op)
{
@@ -3012,6 +3099,11 @@ void MESH_OT_select_face_by_sides(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Loose Operator
+ * \{ */
static int edbm_select_loose_exec(bContext *C, wmOperator *op)
{
@@ -3083,6 +3175,11 @@ void MESH_OT_select_loose(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Mirror Operator
+ * \{ */
static int edbm_select_mirror_exec(bContext *C, wmOperator *op)
{
@@ -3131,7 +3228,11 @@ void MESH_OT_select_mirror(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection");
}
-/* ******************** **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select More Operator
+ * \{ */
static int edbm_select_more_exec(bContext *C, wmOperator *op)
{
@@ -3141,7 +3242,7 @@ static int edbm_select_more_exec(bContext *C, wmOperator *op)
EDBM_select_more(em, use_face_step);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
@@ -3155,13 +3256,19 @@ void MESH_OT_select_more(wmOperatorType *ot)
/* api callbacks */
ot->exec = edbm_select_more_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "use_face_step", true, "Face Step", "Connected faces (instead of edges)");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select More Operator
+ * \{ */
+
static int edbm_select_less_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -3170,7 +3277,7 @@ static int edbm_select_less_exec(bContext *C, wmOperator *op)
EDBM_select_less(em, use_face_step);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
@@ -3184,13 +3291,19 @@ void MESH_OT_select_less(wmOperatorType *ot)
/* api callbacks */
ot->exec = edbm_select_less_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "use_face_step", true, "Face Step", "Connected faces (instead of edges)");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select N'th Operator
+ * \{ */
+
/**
* Check if we're connected to another selected efge.
*/
@@ -3413,13 +3526,18 @@ void MESH_OT_select_nth(wmOperatorType *ot)
void em_setup_viewcontext(bContext *C, ViewContext *vc)
{
- view3d_set_viewcontext(C, vc);
-
+ ED_view3d_viewcontext_init(C, vc);
+
if (vc->obedit) {
vc->em = BKE_editmesh_from_object(vc->obedit);
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Sharp Edges Operator
+ * \{ */
static int edbm_select_sharp_edges_exec(bContext *C, wmOperator *op)
{
@@ -3460,20 +3578,26 @@ void MESH_OT_edges_select_sharp(wmOperatorType *ot)
ot->name = "Select Sharp Edges";
ot->description = "Select all sharp-enough edges";
ot->idname = "MESH_OT_edges_select_sharp";
-
+
/* api callbacks */
ot->exec = edbm_select_sharp_edges_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
prop = RNA_def_float_rotation(ot->srna, "sharpness", 0, NULL, DEG2RADF(0.01f), DEG2RADF(180.0f),
"Sharpness", "", DEG2RADF(1.0f), DEG2RADF(180.0f));
RNA_def_property_float_default(prop, DEG2RADF(30.0f));
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Linked Flat Faces Operator
+ * \{ */
+
static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -3541,20 +3665,26 @@ void MESH_OT_faces_select_linked_flat(wmOperatorType *ot)
ot->name = "Select Linked Flat Faces";
ot->description = "Select linked faces by angle";
ot->idname = "MESH_OT_faces_select_linked_flat";
-
+
/* api callbacks */
ot->exec = edbm_select_linked_flat_faces_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
prop = RNA_def_float_rotation(ot->srna, "sharpness", 0, NULL, DEG2RADF(0.01f), DEG2RADF(180.0f),
"Sharpness", "", DEG2RADF(1.0f), DEG2RADF(180.0f));
RNA_def_property_float_default(prop, DEG2RADF(1.0f));
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Non-Manifold Operator
+ * \{ */
+
static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -3576,12 +3706,12 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op)
/* Selects isolated verts, and edges that do not have 2 neighboring
* faces
*/
-
+
if (em->selectmode == SCE_SELECT_FACE) {
BKE_report(op->reports, RPT_ERROR, "Does not work in face selection mode");
return OPERATOR_CANCELLED;
}
-
+
if (use_verts) {
BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
@@ -3591,7 +3721,7 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op)
}
}
}
-
+
if (use_wire || use_boundary || use_multi_face || use_non_contiguous) {
BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
@@ -3622,11 +3752,11 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot)
ot->name = "Select Non Manifold";
ot->description = "Select all non-manifold vertices or edges";
ot->idname = "MESH_OT_select_non_manifold";
-
+
/* api callbacks */
ot->exec = edbm_select_non_manifold_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -3646,6 +3776,12 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot)
"Vertices connecting multiple face regions");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Random Operator
+ * \{ */
+
static int edbm_select_random_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -3692,9 +3828,9 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op)
else {
EDBM_deselect_flush(em);
}
-
+
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
+
return OPERATOR_FINISHED;
}
@@ -3711,11 +3847,17 @@ void MESH_OT_select_random(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
WM_operator_properties_select_random(ot);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Ungrouped Operator
+ * \{ */
+
static int edbm_select_ungrouped_poll(bContext *C)
{
if (ED_operator_editmesh(C)) {
@@ -3782,6 +3924,11 @@ void MESH_OT_select_ungrouped(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Axis Operator
+ * \{ */
/* BMESH_TODO - some way to select on an arbitrary axis */
static int edbm_select_axis_exec(bContext *C, wmOperator *op)
@@ -3868,6 +4015,12 @@ void MESH_OT_select_axis(wmOperatorType *ot)
RNA_def_float(ot->srna, "threshold", 0.0001f, 0.000001f, 50.0f, "Threshold", "", 0.00001f, 10.0f);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Region to Loop Operator
+ * \{ */
+
static int edbm_region_to_loop_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obedit = CTX_data_edit_object(C);
@@ -3881,22 +4034,22 @@ static int edbm_region_to_loop_exec(bContext *C, wmOperator *UNUSED(op))
BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
BMLoop *l1, *l2;
BMIter liter1, liter2;
-
+
BM_ITER_ELEM (l1, &liter1, f, BM_LOOPS_OF_FACE) {
int tot = 0, totsel = 0;
-
+
BM_ITER_ELEM (l2, &liter2, l1->e, BM_LOOPS_OF_EDGE) {
tot++;
totsel += BM_elem_flag_test(l2->f, BM_ELEM_SELECT) != 0;
}
-
+
if ((tot != totsel && totsel > 0) || (totsel == 1 && tot == 1))
BM_elem_flag_enable(l1->e, BM_ELEM_TAG);
}
}
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
-
+
BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
BM_edge_select_set(em->bm, e, true);
@@ -3931,29 +4084,36 @@ void MESH_OT_region_to_loop(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int loop_find_region(BMLoop *l, int flag,
- GSet *visit_face_set, BMFace ***region_out)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Loop to Region Operator
+ * \{ */
+
+static int loop_find_region(
+ BMLoop *l, int flag,
+ GSet *visit_face_set, BMFace ***region_out)
{
BMFace **region = NULL;
BMFace **stack = NULL;
BLI_array_declare(region);
BLI_array_declare(stack);
BMFace *f;
-
+
BLI_array_append(stack, l->f);
BLI_gset_insert(visit_face_set, l->f);
-
- while (BLI_array_count(stack) > 0) {
+
+ while (BLI_array_len(stack) > 0) {
BMIter liter1, liter2;
BMLoop *l1, *l2;
-
+
f = BLI_array_pop(stack);
BLI_array_append(region, f);
-
+
BM_ITER_ELEM (l1, &liter1, f, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l1->e, flag))
continue;
-
+
BM_ITER_ELEM (l2, &liter2, l1->e, BM_LOOPS_OF_EDGE) {
/* avoids finding same region twice
* (otherwise) the logic works fine without */
@@ -3967,11 +4127,11 @@ static int loop_find_region(BMLoop *l, int flag,
}
}
}
-
+
BLI_array_free(stack);
-
+
*region_out = region;
- return BLI_array_count(region);
+ return BLI_array_len(region);
}
static int verg_radial(const void *va, const void *vb)
@@ -3979,10 +4139,9 @@ static int verg_radial(const void *va, const void *vb)
const BMEdge *e_a = *((const BMEdge **)va);
const BMEdge *e_b = *((const BMEdge **)vb);
- int a, b;
- a = BM_edge_face_count(e_a);
- b = BM_edge_face_count(e_b);
-
+ const int a = BM_edge_face_count(e_a);
+ const int b = BM_edge_face_count(e_b);
+
if (a > b) return -1;
if (a < b) return 1;
return 0;
@@ -4001,7 +4160,7 @@ static int loop_find_regions(BMEditMesh *em, const bool selbigger)
const int edges_len = em->bm->totedgesel;
BMEdge *e, **edges;
int count = 0, i;
-
+
visit_face_set = BLI_gset_ptr_new_ex(__func__, edges_len);
edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__);
@@ -4015,21 +4174,21 @@ static int loop_find_regions(BMEditMesh *em, const bool selbigger)
BM_elem_flag_disable(e, BM_ELEM_TAG);
}
}
-
+
/* sort edges by radial cycle length */
qsort(edges, edges_len, sizeof(*edges), verg_radial);
-
+
for (i = 0; i < edges_len; i++) {
BMIter liter;
BMLoop *l;
BMFace **region = NULL, **region_out;
int c, tot = 0;
-
+
e = edges[i];
-
+
if (!BM_elem_flag_test(e, BM_ELEM_TAG))
continue;
-
+
BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
if (BLI_gset_haskey(visit_face_set, l->f))
continue;
@@ -4051,26 +4210,26 @@ static int loop_find_regions(BMEditMesh *em, const bool selbigger)
MEM_freeN(region_out);
}
}
-
+
if (region) {
int j;
-
+
for (j = 0; j < tot; j++) {
BM_elem_flag_enable(region[j], BM_ELEM_TAG);
BM_ITER_ELEM (l, &liter, region[j], BM_LOOPS_OF_FACE) {
BM_elem_flag_disable(l->e, BM_ELEM_TAG);
}
}
-
+
count += tot;
-
+
MEM_freeN(region);
}
}
-
+
MEM_freeN(edges);
BLI_gset_free(visit_face_set, NULL);
-
+
return count;
}
@@ -4081,25 +4240,23 @@ static int edbm_loop_to_region_exec(bContext *C, wmOperator *op)
BMIter iter;
BMFace *f;
const bool select_bigger = RNA_boolean_get(op->ptr, "select_bigger");
- int a, b;
-
/* find the set of regions with smallest number of total faces */
BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
- a = loop_find_regions(em, select_bigger);
- b = loop_find_regions(em, !select_bigger);
+ const int a = loop_find_regions(em, select_bigger);
+ const int b = loop_find_regions(em, !select_bigger);
BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
loop_find_regions(em, ((a <= b) != select_bigger) ? select_bigger : !select_bigger);
-
+
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
-
+
BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(f, BM_ELEM_TAG) && !BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
BM_face_select_set(em->bm, f, true);
}
}
-
+
EDBM_selectmode_flush(em);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
@@ -4119,9 +4276,8 @@ void MESH_OT_loop_to_region(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
RNA_def_boolean(ot->srna, "select_bigger", 0, "Select Bigger", "Select bigger regions instead of smaller ones");
}
-
-/************************ Select Path Operator *************************/
+/** \} */
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index ff1cd7224cd..bf70cc3fa7e 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -87,6 +87,10 @@
#define USE_FACE_CREATE_SEL_EXTEND
+/* -------------------------------------------------------------------- */
+/** \name Subdivide Operator
+ * \{ */
+
static int edbm_subdivide_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -96,19 +100,20 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op)
const float fractal = RNA_float_get(op->ptr, "fractal") / 2.5f;
const float along_normal = RNA_float_get(op->ptr, "fractal_along_normal");
- if (RNA_boolean_get(op->ptr, "quadtri") &&
+ if (RNA_boolean_get(op->ptr, "quadtri") &&
RNA_enum_get(op->ptr, "quadcorner") == SUBD_CORNER_STRAIGHT_CUT)
{
RNA_enum_set(op->ptr, "quadcorner", SUBD_CORNER_INNERVERT);
}
-
- BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT,
- smooth, SUBD_FALLOFF_LIN, false,
- fractal, along_normal,
- cuts,
- SUBDIV_SELECT_ORIG, RNA_enum_get(op->ptr, "quadcorner"),
- RNA_boolean_get(op->ptr, "quadtri"), true, false,
- RNA_int_get(op->ptr, "seed"));
+
+ BM_mesh_esubdivide(
+ em->bm, BM_ELEM_SELECT,
+ smooth, SUBD_FALLOFF_LIN, false,
+ fractal, along_normal,
+ cuts,
+ SUBDIV_SELECT_ORIG, RNA_enum_get(op->ptr, "quadcorner"),
+ RNA_boolean_get(op->ptr, "quadtri"), true, false,
+ RNA_int_get(op->ptr, "seed"));
EDBM_update_generic(em, true, true);
@@ -159,10 +164,14 @@ void MESH_OT_subdivide(wmOperatorType *ot)
RNA_def_int(ot->srna, "seed", 0, 0, INT_MAX, "Random Seed", "Seed for the random number generator", 0, 255);
}
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* Edge Ring Subdiv
- * (bridge code shares props)
- */
+/** \name Edge Ring Subdivide Operator
+ *
+ * Bridge code shares props.
+ *
+ * \{ */
struct EdgeRingOpSubdProps {
int interp_mode;
@@ -224,11 +233,12 @@ static int edbm_subdivide_edge_ring_exec(bContext *C, wmOperator *op)
mesh_operator_edgering_props_get(op, &op_props);
- if (!EDBM_op_callf(em, op,
- "subdivide_edgering edges=%he interp_mode=%i cuts=%i smooth=%f "
- "profile_shape=%i profile_shape_factor=%f",
- BM_ELEM_SELECT, op_props.interp_mode, op_props.cuts, op_props.smooth,
- op_props.profile_shape, op_props.profile_shape_factor))
+ if (!EDBM_op_callf(
+ em, op,
+ "subdivide_edgering edges=%he interp_mode=%i cuts=%i smooth=%f "
+ "profile_shape=%i profile_shape_factor=%f",
+ BM_ELEM_SELECT, op_props.interp_mode, op_props.cuts, op_props.smooth,
+ op_props.profile_shape, op_props.profile_shape_factor))
{
return OPERATOR_CANCELLED;
}
@@ -256,6 +266,11 @@ void MESH_OT_subdivide_edgering(wmOperatorType *ot)
mesh_operator_edgering_props(ot, 1, 10);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Un-Subdivide Operator
+ * \{ */
static int edbm_unsubdivide_exec(bContext *C, wmOperator *op)
{
@@ -311,7 +326,7 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
ED_view3d_init_mats_rv3d(obedit, ar->regiondata);
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), CTX_data_engine_type(C), 0,
+ CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), 0,
ar, CTX_wm_view3d(C));
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
@@ -337,6 +352,11 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
ED_transform_snap_object_context_destroy(snap_context);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Operator
+ * \{ */
/* Note, these values must match delete_mesh() event values */
enum {
@@ -391,7 +411,7 @@ static int edbm_delete_exec(bContext *C, wmOperator *op)
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
EDBM_update_generic(em, true, true);
-
+
return OPERATOR_FINISHED;
}
@@ -410,13 +430,13 @@ void MESH_OT_delete(wmOperatorType *ot)
ot->name = "Delete";
ot->description = "Delete selected vertices, edges or faces";
ot->idname = "MESH_OT_delete";
-
+
/* api callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = edbm_delete_exec;
-
+
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -425,6 +445,11 @@ void MESH_OT_delete(wmOperatorType *ot)
"Type", "Method used for deleting mesh data");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Loose Operator
+ * \{ */
static bool bm_face_is_loose(BMFace *f)
{
@@ -523,6 +548,11 @@ void MESH_OT_delete_loose(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_faces", false, "Faces", "Remove loose faces");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Collapse Edge Operator
+ * \{ */
static int edbm_collapse_edge_exec(bContext *C, wmOperator *op)
{
@@ -552,6 +582,12 @@ void MESH_OT_edge_collapse(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Create Edge/Face Operator
+ * \{ */
+
static bool edbm_add_edge_face__smooth_get(BMesh *bm)
{
BMEdge *e;
@@ -621,8 +657,9 @@ static BMElem *edbm_add_edge_face_exec__tricky_extend_sel(BMesh *bm)
(BM_edge_share_face_check(ed_pair[0], ed_pair[1]) == false))
)
{
- BMEdge *e_other = BM_edge_exists(BM_edge_other_vert(ed_pair[0], v),
- BM_edge_other_vert(ed_pair[1], v));
+ BMEdge *e_other = BM_edge_exists(
+ BM_edge_other_vert(ed_pair[0], v),
+ BM_edge_other_vert(ed_pair[1], v));
BM_edge_select_set(bm, ed_pair[0], true);
BM_edge_select_set(bm, ed_pair[1], true);
if (e_other) {
@@ -745,13 +782,14 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op)
ele_desel = edbm_add_edge_face_exec__tricky_extend_sel(em->bm);
#endif
- if (!EDBM_op_init(em, &bmop, op,
- "contextual_create geom=%hfev mat_nr=%i use_smooth=%b",
- BM_ELEM_SELECT, em->mat_nr, use_smooth))
+ if (!EDBM_op_init(
+ em, &bmop, op,
+ "contextual_create geom=%hfev mat_nr=%i use_smooth=%b",
+ BM_ELEM_SELECT, em->mat_nr, use_smooth))
{
return OPERATOR_CANCELLED;
}
-
+
BMO_op_exec(em->bm, &bmop);
/* cancel if nothing was done */
@@ -801,16 +839,20 @@ void MESH_OT_edge_face_add(wmOperatorType *ot)
ot->name = "Make Edge/Face";
ot->description = "Add an edge or face to selected";
ot->idname = "MESH_OT_edge_face_add";
-
+
/* api callbacks */
ot->exec = edbm_add_edge_face_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ************************* SEAMS AND EDGES **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mark Edge (Seam) Operator
+ * \{ */
static int edbm_mark_seam_exec(bContext *C, wmOperator *op)
{
@@ -822,7 +864,7 @@ static int edbm_mark_seam_exec(bContext *C, wmOperator *op)
BMEdge *eed;
BMIter iter;
const bool clear = RNA_boolean_get(op->ptr, "clear");
-
+
/* auto-enable seams drawing */
if (clear == 0) {
me->drawflag |= ME_DRAWSEAMS;
@@ -832,7 +874,7 @@ static int edbm_mark_seam_exec(bContext *C, wmOperator *op)
BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
if (!BM_elem_flag_test(eed, BM_ELEM_SELECT) || BM_elem_flag_test(eed, BM_ELEM_HIDDEN))
continue;
-
+
BM_elem_flag_disable(eed, BM_ELEM_SEAM);
}
}
@@ -858,11 +900,11 @@ void MESH_OT_mark_seam(wmOperatorType *ot)
ot->name = "Mark Seam";
ot->idname = "MESH_OT_mark_seam";
ot->description = "(Un)mark selected edges as a seam";
-
+
/* api callbacks */
ot->exec = edbm_mark_seam_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -872,6 +914,12 @@ void MESH_OT_mark_seam(wmOperatorType *ot)
WM_operatortype_props_advanced_begin(ot);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mark Edge (Sharp) Operator
+ * \{ */
+
static int edbm_mark_sharp_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -914,14 +962,14 @@ void MESH_OT_mark_sharp(wmOperatorType *ot)
ot->name = "Mark Sharp";
ot->idname = "MESH_OT_mark_sharp";
ot->description = "(Un)mark selected edges as sharp";
-
+
/* api callbacks */
ot->exec = edbm_mark_sharp_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna, "use_verts", false, "Vertices",
@@ -965,17 +1013,19 @@ static int edbm_vert_connect_exec(bContext *C, wmOperator *op)
}
if (is_pair) {
- if (!EDBM_op_init(em, &bmop, op,
- "connect_vert_pair verts=%eb verts_exclude=%hv faces_exclude=%hf",
- verts, verts_len, BM_ELEM_HIDDEN, BM_ELEM_HIDDEN))
+ if (!EDBM_op_init(
+ em, &bmop, op,
+ "connect_vert_pair verts=%eb verts_exclude=%hv faces_exclude=%hf",
+ verts, verts_len, BM_ELEM_HIDDEN, BM_ELEM_HIDDEN))
{
goto finally;
}
}
else {
- if (!EDBM_op_init(em, &bmop, op,
- "connect_verts verts=%eb faces_exclude=%hf check_degenerate=%b",
- verts, verts_len, BM_ELEM_HIDDEN, check_degenerate))
+ if (!EDBM_op_init(
+ em, &bmop, op,
+ "connect_verts verts=%eb faces_exclude=%hf check_degenerate=%b",
+ verts, verts_len, BM_ELEM_HIDDEN, check_degenerate))
{
goto finally;
}
@@ -1012,15 +1062,20 @@ void MESH_OT_vert_connect(wmOperatorType *ot)
ot->name = "Vertex Connect";
ot->idname = "MESH_OT_vert_connect";
ot->description = "Connect selected vertices of faces, splitting the face";
-
+
/* api callbacks */
ot->exec = edbm_vert_connect_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Split Concave Faces Operator
+ * \{ */
/**
* check that endpoints are verts and only have a single selected edge connected.
@@ -1071,7 +1126,7 @@ static bool bm_vert_connect_select_history(BMesh *bm)
* - Otherwise connect faces.
* - If all edges have been created already, closed the loop.
*/
- if (BLI_listbase_count_ex(&bm->selected, 2) == 2 && (bm->totvertsel > 2)) {
+ if (BLI_listbase_count_at_most(&bm->selected, 2) == 2 && (bm->totvertsel > 2)) {
BMEditSelection *ese;
int tot = 0;
bool changed = false;
@@ -1325,6 +1380,11 @@ void MESH_OT_vert_connect_concave(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Split Non-Planar Faces Operator
+ * \{ */
static int edbm_vert_connect_nonplaner_exec(bContext *C, wmOperator *op)
{
@@ -1369,6 +1429,12 @@ void MESH_OT_vert_connect_nonplanar(wmOperatorType *ot)
RNA_def_property_float_default(prop, DEG2RADF(5.0f));
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Make Planar Faces Operator
+ * \{ */
+
static int edbm_face_make_planar_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -1406,6 +1472,11 @@ void MESH_OT_face_make_planar(wmOperatorType *ot)
RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Split Edge Operator
+ * \{ */
static int edbm_edge_split_exec(bContext *C, wmOperator *op)
{
@@ -1420,7 +1491,7 @@ static int edbm_edge_split_exec(bContext *C, wmOperator *op)
{
return OPERATOR_CANCELLED;
}
-
+
if (em->selectmode == SCE_SELECT_FACE) {
EDBM_select_flush(em);
}
@@ -1436,16 +1507,20 @@ void MESH_OT_edge_split(wmOperatorType *ot)
ot->name = "Edge Split";
ot->idname = "MESH_OT_edge_split";
ot->description = "Split selected edges so that each neighbor face gets its own copy";
-
+
/* api callbacks */
ot->exec = edbm_edge_split_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/****************** add duplicate operator ***************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Duplicate Operator
+ * \{ */
static int edbm_duplicate_exec(bContext *C, wmOperator *op)
{
@@ -1476,7 +1551,7 @@ static int edbm_duplicate_exec(bContext *C, wmOperator *op)
}
EDBM_update_generic(em, true, true);
-
+
return OPERATOR_FINISHED;
}
@@ -1485,7 +1560,7 @@ static int edbm_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNU
WM_cursor_wait(1);
edbm_duplicate_exec(C, op);
WM_cursor_wait(0);
-
+
return OPERATOR_FINISHED;
}
@@ -1495,29 +1570,34 @@ void MESH_OT_duplicate(wmOperatorType *ot)
ot->name = "Duplicate";
ot->description = "Duplicate selected vertices, edges or faces";
ot->idname = "MESH_OT_duplicate";
-
+
/* api callbacks */
ot->invoke = edbm_duplicate_invoke;
ot->exec = edbm_duplicate_exec;
-
+
ot->poll = ED_operator_editmesh;
-
+
/* to give to transform */
RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Flip Normals Operator
+ * \{ */
static int edbm_flip_normals_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
+
if (!EDBM_op_callf(
em, op, "reverse_faces faces=%hf flip_multires=%b",
BM_ELEM_SELECT, true))
{
return OPERATOR_CANCELLED;
}
-
+
EDBM_update_generic(em, true, false);
return OPERATOR_FINISHED;
@@ -1529,15 +1609,21 @@ void MESH_OT_flip_normals(wmOperatorType *ot)
ot->name = "Flip Normals";
ot->description = "Flip the direction of selected faces' normals (and of their vertices)";
ot->idname = "MESH_OT_flip_normals";
-
+
/* api callbacks */
ot->exec = edbm_flip_normals_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Rotate Edge Operator
+ * \{ */
+
/**
* Rotate the edges between selected faces, otherwise rotate the selected edges.
*/
@@ -1571,7 +1657,7 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op)
}
}
}
-
+
/* ok, we don't have two adjacent faces, but we do have two selected ones.
* that's an error condition.*/
if (tot == 0) {
@@ -1630,12 +1716,17 @@ void MESH_OT_edge_rotate(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", "");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Hide Operator
+ * \{ */
static int edbm_hide_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
+
EDBM_mesh_hide(em, RNA_boolean_get(op->ptr, "unselected"));
EDBM_update_generic(em, true, false);
@@ -1649,18 +1740,24 @@ void MESH_OT_hide(wmOperatorType *ot)
ot->name = "Hide Selection";
ot->idname = "MESH_OT_hide";
ot->description = "Hide (un)selected vertices, edges or faces";
-
+
/* api callbacks */
ot->exec = edbm_hide_exec;
ot->poll = ED_operator_editmesh;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
RNA_def_boolean(ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Reveal Operator
+ * \{ */
+
static int edbm_reveal_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -1680,22 +1777,28 @@ void MESH_OT_reveal(wmOperatorType *ot)
ot->name = "Reveal Hidden";
ot->idname = "MESH_OT_reveal";
ot->description = "Reveal all hidden vertices, edges and faces";
-
+
/* api callbacks */
ot->exec = edbm_reveal_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Recalculate Normals Operator
+ * \{ */
+
static int edbm_normals_make_consistent_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
+
/* doflip has to do with bmesh_rationalize_normals, it's an internal
* thing */
if (!EDBM_op_callf(em, op, "recalc_face_normals faces=%hf", BM_ELEM_SELECT))
@@ -1716,18 +1819,22 @@ void MESH_OT_normals_make_consistent(wmOperatorType *ot)
ot->name = "Make Normals Consistent";
ot->description = "Make face and vertex normals point either outside or inside the mesh";
ot->idname = "MESH_OT_normals_make_consistent";
-
+
/* api callbacks */
ot->exec = edbm_normals_make_consistent_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
RNA_def_boolean(ot->srna, "inside", false, "Inside", "");
}
+/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Smooth Vertex Operator
+ * \{ */
static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
{
@@ -1751,12 +1858,12 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
}
/* if there is a mirror modifier with clipping, flag the verts that
- * are within tolerance of the plane(s) of reflection
+ * are within tolerance of the plane(s) of reflection
*/
for (md = obedit->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) {
MirrorModifierData *mmd = (MirrorModifierData *)md;
-
+
if (mmd->flag & MOD_MIR_CLIPPING) {
if (mmd->flag & MOD_MIR_AXIS_X)
mirrx = true;
@@ -1775,10 +1882,11 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
repeat = 1;
for (i = 0; i < repeat; i++) {
- if (!EDBM_op_callf(em, op,
- "smooth_vert verts=%hv factor=%f mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b "
- "clip_dist=%f use_axis_x=%b use_axis_y=%b use_axis_z=%b",
- BM_ELEM_SELECT, fac, mirrx, mirry, mirrz, clip_dist, xaxis, yaxis, zaxis))
+ if (!EDBM_op_callf(
+ em, op,
+ "smooth_vert verts=%hv factor=%f mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b "
+ "clip_dist=%f use_axis_x=%b use_axis_y=%b use_axis_z=%b",
+ BM_ELEM_SELECT, fac, mirrx, mirry, mirrz, clip_dist, xaxis, yaxis, zaxis))
{
return OPERATOR_CANCELLED;
}
@@ -1793,19 +1901,20 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
EDBM_update_generic(em, true, false);
return OPERATOR_FINISHED;
-}
-
+}
+
+
void MESH_OT_vertices_smooth(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Smooth Vertex";
ot->description = "Flatten angles of selected vertices";
ot->idname = "MESH_OT_vertices_smooth";
-
+
/* api callbacks */
ot->exec = edbm_do_smooth_vertex_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1819,6 +1928,12 @@ void MESH_OT_vertices_smooth(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "zaxis", true, "Z-Axis", "Smooth along the Z axis");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Laplacian Vertex Smooth Operator
+ * \{ */
+
static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -1832,13 +1947,13 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
BMIter fiter;
BMFace *f;
- /* Check if select faces are triangles */
+ /* Check if select faces are triangles */
BM_ITER_MESH (f, &fiter, em->bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
if (f->len > 4) {
BKE_report(op->reports, RPT_WARNING, "Selected faces must be triangles or quads");
return OPERATOR_CANCELLED;
- }
+ }
}
}
@@ -1856,11 +1971,12 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
preserve_volume = RNA_boolean_get(op->ptr, "preserve_volume");
if (!repeat)
repeat = 1;
-
+
for (i = 0; i < repeat; i++) {
- if (!EDBM_op_callf(em, op,
- "smooth_laplacian_vert verts=%hv lambda_factor=%f lambda_border=%f use_x=%b use_y=%b use_z=%b preserve_volume=%b",
- BM_ELEM_SELECT, lambda_factor, lambda_border, usex, usey, usez, preserve_volume))
+ if (!EDBM_op_callf(
+ em, op,
+ "smooth_laplacian_vert verts=%hv lambda_factor=%f lambda_border=%f use_x=%b use_y=%b use_z=%b preserve_volume=%b",
+ BM_ELEM_SELECT, lambda_factor, lambda_border, usex, usey, usez, preserve_volume))
{
return OPERATOR_CANCELLED;
}
@@ -1883,11 +1999,11 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot)
ot->name = "Laplacian Smooth Vertex";
ot->description = "Laplacian smooth of selected vertices";
ot->idname = "MESH_OT_vertices_smooth_laplacian";
-
+
/* api callbacks */
ot->exec = edbm_do_smooth_laplacian_vertex_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1906,7 +2022,11 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "preserve_volume", true, "Preserve Volume", "Apply volume preservation after smooth");
}
-/********************** Smooth/Solid Operators *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Faces Smooth Shading Operator
+ * \{ */
static void mesh_set_smooth_faces(BMEditMesh *em, short smooth)
{
@@ -1914,7 +2034,7 @@ static void mesh_set_smooth_faces(BMEditMesh *em, short smooth)
BMFace *efa;
if (em == NULL) return;
-
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_elem_flag_set(efa, BM_ELEM_SMOOTH, smooth);
@@ -1949,6 +2069,12 @@ void MESH_OT_faces_shade_smooth(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Faces Flat Shading Operator
+ * \{ */
+
static int edbm_faces_shade_flat_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obedit = CTX_data_edit_object(C);
@@ -1976,8 +2102,11 @@ void MESH_OT_faces_shade_flat(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
-/********************** UV/Color Operators *************************/
+/* -------------------------------------------------------------------- */
+/** \name UV/Color Rotate/Reverse Operator
+ * \{ */
static int edbm_rotate_uvs_exec(bContext *C, wmOperator *op)
{
@@ -2147,6 +2276,11 @@ void MESH_OT_colors_reverse(wmOperatorType *ot)
//RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Merge Vertices Operator
+ * \{ */
enum {
MESH_MERGE_LAST = 1,
@@ -2183,7 +2317,7 @@ static bool merge_firstlast(BMEditMesh *em, const bool use_first, const bool use
if (!BM_elem_flag_test(mergevert, BM_ELEM_SELECT))
return false;
-
+
if (use_uvmerge) {
if (!EDBM_op_callf(em, wmop, "pointmerge_facedata verts=%hv vert_snap=%e", BM_ELEM_SELECT, mergevert))
return false;
@@ -2195,8 +2329,9 @@ static bool merge_firstlast(BMEditMesh *em, const bool use_first, const bool use
return true;
}
-static bool merge_target(BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob,
- const bool use_cursor, const bool use_uvmerge, wmOperator *wmop)
+static bool merge_target(
+ BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob,
+ const bool use_cursor, const bool use_uvmerge, wmOperator *wmop)
{
BMIter iter;
BMVert *v;
@@ -2217,7 +2352,7 @@ static bool merge_target(BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob,
add_v3_v3(cent, v->co);
i++;
}
-
+
if (!i)
return false;
@@ -2229,7 +2364,7 @@ static bool merge_target(BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob,
if (!vco)
return false;
-
+
if (use_uvmerge) {
if (!EDBM_op_callf(em, wmop, "average_vert_facedata verts=%hv", BM_ELEM_SELECT))
return false;
@@ -2296,14 +2431,14 @@ static const EnumPropertyItem merge_type_items[] = {
};
static const EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
-{
+{
Object *obedit;
EnumPropertyItem *item = NULL;
int totitem = 0;
-
+
if (!C) /* needed for docs */
return merge_type_items;
-
+
obedit = CTX_data_edit_object(C);
if (obedit && obedit->type == OB_MESH) {
BMEditMesh *em = BKE_editmesh_from_object(obedit);
@@ -2333,7 +2468,7 @@ static const EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *UNUSED(
return item;
}
-
+
return NULL;
}
@@ -2361,6 +2496,11 @@ void MESH_OT_merge(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "uvs", false, "UVs", "Move UVs according to merge");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Remove Doubles Operator
+ * \{ */
static int edbm_remove_doubles_exec(bContext *C, wmOperator *op)
{
@@ -2383,9 +2523,10 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op)
if (use_unselected) {
- EDBM_op_init(em, &bmop, op,
- "automerge verts=%hv dist=%f",
- BM_ELEM_SELECT, threshold);
+ 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)) {
@@ -2393,9 +2534,10 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op)
}
}
else {
- EDBM_op_init(em, &bmop, op,
- "find_doubles verts=%hv dist=%f",
- BM_ELEM_SELECT, threshold);
+ EDBM_op_init(
+ em, &bmop, op,
+ "find_doubles verts=%hv dist=%f",
+ BM_ELEM_SELECT, threshold);
BMO_op_exec(em->bm, &bmop);
if (!EDBM_op_callf(em, op, "weld_verts targetmap=%S", &bmop, "targetmap.out")) {
@@ -2407,7 +2549,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
}
-
+
count = totvert_orig - em->bm->totvert;
BKE_reportf(op->reports, RPT_INFO, "Removed %d vertices", count);
@@ -2439,8 +2581,11 @@ void MESH_OT_remove_doubles(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_unselected", false, "Unselected", "Merge selected to other unselected vertices");
}
+/** \} */
-/************************ Shape Operators *************************/
+/* -------------------------------------------------------------------- */
+/** \name Shape Key Propagate Operator
+ * \{ */
/* BMESH_TODO this should be properly encapsulated in a bmop. but later.*/
static void shape_propagate(BMEditMesh *em, wmOperator *op)
@@ -2454,7 +2599,7 @@ static void shape_propagate(BMEditMesh *em, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "Mesh does not have shape keys");
return;
}
-
+
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN))
continue;
@@ -2505,6 +2650,12 @@ void MESH_OT_shape_propagate_to_all(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Blend from Shape Operator
+ * \{ */
+
/* BMESH_TODO this should be properly encapsulated in a bmop. but later.*/
static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
{
@@ -2531,23 +2682,23 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
if (key) {
kb = BLI_findlink(&key->block, shape);
}
-
+
/* perform blending on selected vertices*/
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN))
continue;
-
+
/* get coordinates of shapekey we're blending from */
sco = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, shape);
copy_v3_v3(co, sco);
-
+
if (use_add) {
/* in add mode, we add relative shape key offset */
if (kb) {
const float *rco = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, kb->relative);
sub_v3_v3v3(co, co, rco);
}
-
+
madd_v3_v3fl(eve->co, co, blend);
}
else {
@@ -2562,7 +2713,7 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
}
static const EnumPropertyItem *shape_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
-{
+{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em;
EnumPropertyItem *item = NULL;
@@ -2635,6 +2786,12 @@ void MESH_OT_blend_from_shape(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "add", true, "Add", "Add rather than blend between shapes");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Solidify Mesh Operator
+ * \{ */
+
static int edbm_solidify_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -2689,6 +2846,12 @@ void MESH_OT_solidify(wmOperatorType *ot)
RNA_def_property_ui_range(prop, -10.0, 10.0, 0.1, 4);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Knife Subdivide Operator
+ * \{ */
+
/* ******************************************************************** */
/* Knife Subdivide Tool. Subdivides edges intersected by a mouse trail
* drawn by user.
@@ -2722,8 +2885,9 @@ static const EnumPropertyItem knife_items[] = {
/* bm_edge_seg_isect() Determines if and where a mouse trail intersects an BMEdge */
-static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2],
- float (*mouse_path)[2], int len, char mode, int *isected)
+static float bm_edge_seg_isect(
+ const float sco_a[2], const float sco_b[2],
+ float (*mouse_path)[2], int len, char mode, int *isected)
{
#define MAXSLOPE 100000
float x11, y11, x12 = 0, y12 = 0, x2max, x2min, y2max;
@@ -2732,17 +2896,17 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2],
float yi, x1min, x1max, y1max, y1min, perc = 0;
float threshold = 0.0;
int i;
-
+
//threshold = 0.000001; /* tolerance for vertex intersection */
// XXX threshold = scene->toolsettings->select_thresh / 100;
-
+
/* Get screen coords of verts */
x21 = sco_a[0];
y21 = sco_a[1];
-
+
x22 = sco_b[0];
y22 = sco_b[1];
-
+
xdiff2 = (x22 - x21);
if (xdiff2) {
m2 = (y22 - y21) / xdiff2;
@@ -2768,7 +2932,7 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2],
}
x12 = mouse_path[i][0];
y12 = mouse_path[i][1];
-
+
/* test e->v1 */
if ((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)) {
perc = 0;
@@ -2783,7 +2947,7 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2],
}
}
}
-
+
/* now check for edge intersect (may produce vertex intersection as well) */
for (i = 0; i < len; i++) {
if (i > 0) {
@@ -2796,14 +2960,14 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2],
}
x12 = mouse_path[i][0];
y12 = mouse_path[i][1];
-
+
/* Perp. Distance from point to line */
if (m2 != MAXSLOPE) dist = (y12 - m2 * x12 - b2); /* /sqrt(m2 * m2 + 1); Only looking for */
/* change in sign. Skip extra math */
else dist = x22 - x12;
-
+
if (i == 0) lastdist = dist;
-
+
/* if dist changes sign, and intersect point in edge's Bound Box */
if ((lastdist * dist) <= 0) {
xdiff1 = (x12 - x11); /* Equation of line between last 2 points */
@@ -2819,14 +2983,14 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2],
x2min = min_ff(x21, x22) - 0.001f; /* due to round off error */
y2max = max_ff(y21, y22) + 0.001f;
y2min = min_ff(y21, y22) - 0.001f;
-
+
/* Found an intersect, calc intersect point */
if (m1 == m2) { /* co-incident lines */
/* cut at 50% of overlap area */
x1max = max_ff(x11, x12);
x1min = min_ff(x11, x12);
xi = (min_ff(x2max, x1max) + max_ff(x2min, x1min)) / 2.0f;
-
+
y1max = max_ff(y11, y12);
y1min = min_ff(y11, y12);
yi = (min_ff(y2max, y1max) + max_ff(y2min, y1min)) / 2.0f;
@@ -2843,7 +3007,7 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2],
xi = (b1 - b2) / (m2 - m1);
yi = (b1 * m2 - m1 * b2) / (m2 - m1);
}
-
+
/* Intersect inside bounding box of edge?*/
if ((xi >= x2min) && (xi <= x2max) && (yi <= y2max) && (yi >= y2min)) {
/* test for vertex intersect that may be 'close enough'*/
@@ -2866,7 +3030,7 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2],
if ((m2 <= 1.0f) && (m2 >= -1.0f)) perc = (xi - x21) / (x22 - x21);
else perc = (yi - y21) / (y22 - y21); /* lower slope more accurate */
//isect = 32768.0 * (perc + 0.0000153); /* Percentage in 1 / 32768ths */
-
+
break;
}
}
@@ -2895,11 +3059,11 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
/* allocd vars */
float (*screen_vert_coords)[2], (*sco)[2], (*mouse_path)[2];
-
+
/* edit-object needed for matrix, and ar->regiondata for projections to work */
if (ELEM(NULL, obedit, ar, ar->regiondata))
return OPERATOR_CANCELLED;
-
+
if (bm->totvertsel < 2) {
BKE_report(op->reports, RPT_ERROR, "No edges are selected to operate on");
return OPERATOR_CANCELLED;
@@ -2984,7 +3148,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
BMO_slot_bool_set(bmop.slots_in, "use_grid_fill", false);
BMO_slot_float_set(bmop.slots_in, "radius", 0);
-
+
BMO_op_exec(bm, &bmop);
if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
@@ -3002,13 +3166,13 @@ void MESH_OT_knife_cut(wmOperatorType *ot)
ot->name = "Knife Cut";
ot->description = "Cut selected edges and faces into parts";
ot->idname = "MESH_OT_knife_cut";
-
+
ot->invoke = WM_gesture_lines_invoke;
ot->modal = WM_gesture_lines_modal;
ot->exec = edbm_knife_cut_exec;
-
+
ot->poll = EDBM_view3d_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -3018,13 +3182,16 @@ void MESH_OT_knife_cut(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
RNA_def_enum(ot->srna, "type", knife_items, KNIFE_EXACT, "Type", "");
-
+
/* internal */
RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, BC_NUMCURSORS, "Cursor", "", 0, BC_NUMCURSORS);
}
+/** \} */
-/* *************** Operator: separate parts *************/
+/* -------------------------------------------------------------------- */
+/** \name Separate Parts Operator
+ * \{ */
enum {
MESH_SEPARATE_SELECTED = 0,
@@ -3075,7 +3242,7 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, ViewLayer *view_lay
BM_mesh_free(bm_new);
((Mesh *)base_new->object->data)->edit_btmesh = NULL;
-
+
return base_new;
}
@@ -3304,7 +3471,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
ViewLayer *view_layer = CTX_data_view_layer(C);
const int type = RNA_enum_get(op->ptr, "type");
int retval = 0;
-
+
if (ED_operator_editmesh(C)) {
Base *base = CTX_data_active_base(C);
BMEditMesh *em = BKE_editmesh_from_object(base->object);
@@ -3374,7 +3541,11 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
}
if (retval_iter) {
- BM_mesh_bm_to_me(bm_old, me, (&(struct BMeshToMeshParams){0}));
+ BM_mesh_bm_to_me(
+ bm_old, me,
+ (&(struct BMeshToMeshParams){
+ .calc_object_remap = true,
+ }));
DEG_id_tag_update(&me->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
@@ -3413,18 +3584,23 @@ void MESH_OT_separate(wmOperatorType *ot)
ot->name = "Separate";
ot->description = "Separate selected geometry into a new mesh";
ot->idname = "MESH_OT_separate";
-
+
/* api callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = edbm_separate_exec;
ot->poll = ED_operator_scene_editable; /* object and editmode */
-
+
/* flags */
ot->flag = OPTYPE_UNDO;
-
+
ot->prop = RNA_def_enum(ot->srna, "type", prop_separate_types, MESH_SEPARATE_SELECTED, "Type", "");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Triangle Fill Operator
+ * \{ */
static int edbm_fill_exec(bContext *C, wmOperator *op)
{
@@ -3446,9 +3622,9 @@ static int edbm_fill_exec(bContext *C, wmOperator *op)
{
return OPERATOR_CANCELLED;
}
-
+
BMO_op_exec(em->bm, &bmop);
-
+
if (totface_orig != em->bm->totface) {
/* select new geometry */
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_FACE | BM_EDGE, BM_ELEM_SELECT, true);
@@ -3486,9 +3662,11 @@ void MESH_OT_fill(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_beauty", true, "Beauty", "Use best triangulation division");
}
+/** \} */
/* -------------------------------------------------------------------- */
-/* Grid Fill (and helper functions) */
+/** \name Grid Fill Operator
+ * \{ */
static bool bm_edge_test_fill_grid_cb(BMEdge *e, void *UNUSED(bm_v))
{
@@ -3584,7 +3762,7 @@ static void edbm_fill_grid_prepare(BMesh *bm, int offset, int *r_span, bool span
*
* note: we may have already checked 'edbm_fill_grid_vert_tag_angle()' on each
* vert, but advantage of de-duplicating is minimal. */
- struct SortPointerByFloat *ele_sort = MEM_mallocN(sizeof(*ele_sort) * verts_len, __func__);
+ struct SortPtrByFloat *ele_sort = MEM_mallocN(sizeof(*ele_sort) * verts_len, __func__);
LinkData *v_link;
for (v_link = verts->first, i = 0; v_link; v_link = v_link->next, i++) {
BMVert *v = v_link->data;
@@ -3679,10 +3857,11 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
/* end tricky prepare code */
- if (!EDBM_op_init(em, &bmop, op,
- "grid_fill edges=%he mat_nr=%i use_smooth=%b use_interp_simple=%b",
- use_prepare ? BM_ELEM_TAG : BM_ELEM_SELECT,
- em->mat_nr, use_smooth, use_interp_simple))
+ if (!EDBM_op_init(
+ em, &bmop, op,
+ "grid_fill edges=%he mat_nr=%i use_smooth=%b use_interp_simple=%b",
+ use_prepare ? BM_ELEM_TAG : BM_ELEM_SELECT,
+ em->mat_nr, use_smooth, use_interp_simple))
{
return OPERATOR_CANCELLED;
}
@@ -3732,6 +3911,12 @@ void MESH_OT_fill_grid(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_interp_simple", false, "Simple Blending", "");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Hole Fill Operator
+ * \{ */
+
static int edbm_fill_holes_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -3771,6 +3956,12 @@ void MESH_OT_fill_holes(wmOperatorType *ot)
"Sides", "Number of sides in hole required to fill (zero fills all holes)", 0, 100);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Beauty Fill Operator
+ * \{ */
+
static int edbm_beautify_fill_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -3788,9 +3979,10 @@ static int edbm_beautify_fill_exec(bContext *C, wmOperator *op)
BMEdge *e;
BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_set(e, BM_ELEM_TAG,
- (BM_elem_flag_test(e, BM_ELEM_SELECT) &&
- BM_edge_calc_face_angle_ex(e, angle_max) < angle_limit));
+ BM_elem_flag_set(
+ e, BM_ELEM_TAG,
+ (BM_elem_flag_test(e, BM_ELEM_SELECT) &&
+ BM_edge_calc_face_angle_ex(e, angle_max) < angle_limit));
}
@@ -3806,7 +3998,7 @@ static int edbm_beautify_fill_exec(bContext *C, wmOperator *op)
}
EDBM_update_generic(em, true, true);
-
+
return OPERATOR_FINISHED;
}
@@ -3832,8 +4024,11 @@ void MESH_OT_beautify_fill(wmOperatorType *ot)
RNA_def_property_float_default(prop, DEG2RADF(180.0f));
}
+/** \} */
-/********************** Poke Face **********************/
+/* -------------------------------------------------------------------- */
+/** \name Poke Face Operator
+ * \{ */
static int edbm_poke_face_exec(bContext *C, wmOperator *op)
{
@@ -3893,7 +4088,11 @@ void MESH_OT_poke(wmOperatorType *ot)
"Poke Center", "Poke Face Center Calculation");
}
-/********************** Quad/Tri Operators *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Triangulate Face Operator
+ * \{ */
static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op)
{
@@ -3948,6 +4147,12 @@ void MESH_OT_quads_convert_to_tris(wmOperatorType *ot)
"Polygon Method", "Method for splitting the polygons into triangles");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Convert to Quads Operator
+ * \{ */
+
static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -4038,10 +4243,10 @@ void MESH_OT_tris_convert_to_quads(wmOperatorType *ot)
join_triangle_props(ot);
}
+/** \} */
/* -------------------------------------------------------------------- */
-
-/** \name Decimate
+/** \name Decimate Operator
*
* \note The function to decimate is intended for use as a modifier,
* while its handy allow access as a tool - this does cause access to be a little awkward
@@ -4227,9 +4432,9 @@ void MESH_OT_decimate(wmOperatorType *ot)
/** \} */
-
/* -------------------------------------------------------------------- */
-/* Dissolve */
+/** \name Dissolve Vertices Operator
+ * \{ */
static void edbm_dissolve_prop__use_verts(wmOperatorType *ot, bool value, int flag)
{
@@ -4261,9 +4466,10 @@ static int edbm_dissolve_verts_exec(bContext *C, wmOperator *op)
const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split");
const bool use_boundary_tear = RNA_boolean_get(op->ptr, "use_boundary_tear");
- if (!EDBM_op_callf(em, op,
- "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
- BM_ELEM_SELECT, use_face_split, use_boundary_tear))
+ if (!EDBM_op_callf(
+ em, op,
+ "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
+ BM_ELEM_SELECT, use_face_split, use_boundary_tear))
{
return OPERATOR_CANCELLED;
}
@@ -4291,6 +4497,12 @@ void MESH_OT_dissolve_verts(wmOperatorType *ot)
edbm_dissolve_prop__use_boundary_tear(ot);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Dissolve Edges Operator
+ * \{ */
+
static int edbm_dissolve_edges_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -4299,9 +4511,10 @@ static int edbm_dissolve_edges_exec(bContext *C, wmOperator *op)
const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split");
- if (!EDBM_op_callf(em, op,
- "dissolve_edges edges=%he use_verts=%b use_face_split=%b",
- BM_ELEM_SELECT, use_verts, use_face_split))
+ if (!EDBM_op_callf(
+ em, op,
+ "dissolve_edges edges=%he use_verts=%b use_face_split=%b",
+ BM_ELEM_SELECT, use_verts, use_face_split))
{
return OPERATOR_CANCELLED;
}
@@ -4329,6 +4542,12 @@ void MESH_OT_dissolve_edges(wmOperatorType *ot)
edbm_dissolve_prop__use_face_split(ot);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Dissolve Faces Operator
+ * \{ */
+
static int edbm_dissolve_faces_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -4367,6 +4586,11 @@ void MESH_OT_dissolve_faces(wmOperatorType *ot)
edbm_dissolve_prop__use_verts(ot, false, 0);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Dissolve (Context Sensitive) Operator
+ * \{ */
static int edbm_dissolve_mode_exec(bContext *C, wmOperator *op)
{
@@ -4412,6 +4636,12 @@ void MESH_OT_dissolve_mode(wmOperatorType *ot)
edbm_dissolve_prop__use_boundary_tear(ot);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Limited Dissolve Operator
+ * \{ */
+
static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -4489,6 +4719,12 @@ void MESH_OT_dissolve_limited(wmOperatorType *ot)
"Delimit dissolve operation");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Degenerate Dissolve Operator
+ * \{ */
+
static int edbm_dissolve_degenerate_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -4533,6 +4769,11 @@ void MESH_OT_dissolve_degenerate(wmOperatorType *ot)
"Minimum distance between elements to merge", 1e-5f, 10.0f);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Edge-Loop Operator
+ * \{ */
/* internally uses dissolve */
static int edbm_delete_edgeloop_exec(bContext *C, wmOperator *op)
@@ -4559,9 +4800,10 @@ static int edbm_delete_edgeloop_exec(bContext *C, wmOperator *op)
}
}
- if (!EDBM_op_callf(em, op,
- "dissolve_edges edges=%he use_verts=%b use_face_split=%b",
- BM_ELEM_SELECT, true, use_face_split))
+ if (!EDBM_op_callf(
+ em, op,
+ "dissolve_edges edges=%he use_verts=%b use_face_split=%b",
+ BM_ELEM_SELECT, true, use_face_split))
{
return OPERATOR_CANCELLED;
}
@@ -4593,6 +4835,12 @@ void MESH_OT_delete_edgeloop(wmOperatorType *ot)
"Split off face corners to maintain surrounding geometry");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Split Geometry Operator
+ * \{ */
+
static int edbm_split_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_edit_object(C);
@@ -4630,16 +4878,21 @@ void MESH_OT_split(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/******************************************************************************
- * qsort routines.
- * Now unified, for vertices/edges/faces. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Sort Geometry Elements Operator
+ *
+ * Unified for vertices/edges/faces.
+ *
+ * \{ */
enum {
SRT_VIEW_ZAXIS = 1, /* Use view Z (deep) axis. */
SRT_VIEW_XAXIS, /* Use view X (left to right) axis. */
SRT_CURSOR_DISTANCE, /* Use distance from element to 3D cursor. */
SRT_MATERIAL, /* Face only: use mat number. */
- SRT_SELECTED, /* Move selected elements in first, without modifying
+ SRT_SELECTED, /* Move selected elements in first, without modifying
* relative order of selected and unselected elements. */
SRT_RANDOMIZE, /* Randomize selected elements. */
SRT_REVERSE, /* Reverse current order of selected elements. */
@@ -4658,10 +4911,11 @@ static int bmelemsort_comp(const void *v1, const void *v2)
}
/* Reorders vertices/edges/faces using a given methods. Loops are not supported. */
-static void sort_bmelem_flag(Scene *scene, Object *ob,
- View3D *v3d, RegionView3D *rv3d,
- const int types, const int flag, const int action,
- const int reverse, const unsigned int seed)
+static void sort_bmelem_flag(
+ Scene *scene, Object *ob,
+ View3D *v3d, RegionView3D *rv3d,
+ const int types, const int flag, const int action,
+ const int reverse, const unsigned int seed)
{
BMEditMesh *em = BKE_editmesh_from_object(ob);
@@ -5127,8 +5381,9 @@ static int edbm_sort_elements_exec(bContext *C, wmOperator *op)
RNA_enum_set(op->ptr, "elements", elem_types);
}
- sort_bmelem_flag(scene, ob, v3d, rv3d,
- elem_types, BM_ELEM_SELECT, action, use_reverse, seed);
+ sort_bmelem_flag(
+ scene, ob, v3d, rv3d,
+ elem_types, BM_ELEM_SELECT, action, use_reverse, seed);
return OPERATOR_FINISHED;
}
@@ -5217,7 +5472,11 @@ void MESH_OT_sort_elements(wmOperatorType *ot)
RNA_def_int(ot->srna, "seed", 0, 0, INT_MAX, "Seed", "Seed for random-based operations", 0, 255);
}
-/****** end of qsort stuff ****/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Noise (Deform Vertices) Operator
+ * \{ */
static int edbm_noise_exec(bContext *C, wmOperator *op)
{
@@ -5250,7 +5509,7 @@ static int edbm_noise_exec(bContext *C, wmOperator *op)
vec[0] = fac * (b2 - BLI_hnoise(tex->noisesize, eve->co[0] + ofs, eve->co[1], eve->co[2]));
vec[1] = fac * (b2 - BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1] + ofs, eve->co[2]));
vec[2] = fac * (b2 - BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2] + ofs));
-
+
add_v3_v3(eve->co, vec);
}
}
@@ -5291,6 +5550,11 @@ void MESH_OT_noise(wmOperatorType *ot)
RNA_def_float(ot->srna, "factor", 0.1f, -1e4f, 1e4f, "Factor", "", 0.0f, 1.0f);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Bridge Operator
+ * \{ */
enum {
MESH_BRIDGELOOP_SINGLE = 0,
@@ -5377,9 +5641,10 @@ static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op)
edge_hflag = BM_ELEM_SELECT;
}
- EDBM_op_init(em, &bmop, op,
- "bridge_loops edges=%he use_pairs=%b use_cyclic=%b use_merge=%b merge_factor=%f twist_offset=%i",
- edge_hflag, use_pairs, use_cyclic, use_merge, merge_factor, twist_offset);
+ EDBM_op_init(
+ em, &bmop, op,
+ "bridge_loops edges=%he use_pairs=%b use_cyclic=%b use_merge=%b merge_factor=%f twist_offset=%i",
+ edge_hflag, use_pairs, use_cyclic, use_merge, merge_factor, twist_offset);
if (use_faces && totface_del) {
int i;
@@ -5387,9 +5652,10 @@ static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op)
for (i = 0; i < totface_del; i++) {
BM_elem_flag_enable(totface_del_arr[i], BM_ELEM_TAG);
}
- BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS,
- "delete geom=%hf context=%i",
- BM_ELEM_TAG, DEL_FACES_KEEP_BOUNDARY);
+ BMO_op_callf(
+ em->bm, BMO_FLAG_DEFAULTS,
+ "delete geom=%hf context=%i",
+ BM_ELEM_TAG, DEL_FACES_KEEP_BOUNDARY);
}
BMO_op_exec(em->bm, &bmop);
@@ -5455,11 +5721,11 @@ void MESH_OT_bridge_edge_loops(wmOperatorType *ot)
ot->name = "Bridge Edge Loops";
ot->description = "Make faces between two or more edge loops";
ot->idname = "MESH_OT_bridge_edge_loops";
-
+
/* api callbacks */
ot->exec = edbm_bridge_edge_loops_exec;
ot->poll = ED_operator_editmesh;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -5473,6 +5739,12 @@ void MESH_OT_bridge_edge_loops(wmOperatorType *ot)
mesh_operator_edgering_props(ot, 0, 0);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Wire-Frame Operator
+ * \{ */
+
static int edbm_wireframe_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -5487,11 +5759,12 @@ static int edbm_wireframe_exec(bContext *C, wmOperator *op)
const float thickness = RNA_float_get(op->ptr, "thickness");
const float offset = RNA_float_get(op->ptr, "offset");
- EDBM_op_init(em, &bmop, op,
- "wireframe faces=%hf use_replace=%b use_boundary=%b use_even_offset=%b use_relative_offset=%b "
- "use_crease=%b crease_weight=%f thickness=%f offset=%f",
- BM_ELEM_SELECT, use_replace, use_boundary, use_even_offset, use_relative_offset,
- use_crease, crease_weight, thickness, offset);
+ EDBM_op_init(
+ em, &bmop, op,
+ "wireframe faces=%hf use_replace=%b use_boundary=%b use_even_offset=%b use_relative_offset=%b "
+ "use_crease=%b crease_weight=%f thickness=%f offset=%f",
+ BM_ELEM_SELECT, use_replace, use_boundary, use_even_offset, use_relative_offset,
+ use_crease, crease_weight, thickness, offset);
BMO_op_exec(em->bm, &bmop);
@@ -5537,6 +5810,12 @@ void MESH_OT_wireframe(wmOperatorType *ot)
RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 2);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Offset Edge-Loop Operator
+ * \{ */
+
static int edbm_offset_edgeloop_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -5591,6 +5870,12 @@ void MESH_OT_offset_edge_loops(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_cap_endpoint", false, "Cap Endpoint", "Extend loop around end-points");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Convex Hull Operator
+ * \{ */
+
#ifdef WITH_BULLET
static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
{
@@ -5598,10 +5883,11 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMOperator bmop;
- EDBM_op_init(em, &bmop, op, "convex_hull input=%hvef "
- "use_existing_faces=%b",
- BM_ELEM_SELECT,
- RNA_boolean_get(op->ptr, "use_existing_faces"));
+ EDBM_op_init(
+ em, &bmop, op, "convex_hull input=%hvef "
+ "use_existing_faces=%b",
+ BM_ELEM_SELECT,
+ RNA_boolean_get(op->ptr, "use_existing_faces"));
BMO_op_exec(em->bm, &bmop);
/* Hull fails if input is coplanar */
@@ -5614,8 +5900,9 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
/* Delete unused vertices, edges, and faces */
if (RNA_boolean_get(op->ptr, "delete_unused")) {
- if (!EDBM_op_callf(em, op, "delete geom=%S context=%i",
- &bmop, "geom_unused.out", DEL_ONLYTAGGED))
+ if (!EDBM_op_callf(
+ em, op, "delete geom=%S context=%i",
+ &bmop, "geom_unused.out", DEL_ONLYTAGGED))
{
EDBM_op_finish(em, &bmop, op, true);
return OPERATOR_CANCELLED;
@@ -5624,8 +5911,9 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
/* Delete hole edges/faces */
if (RNA_boolean_get(op->ptr, "make_holes")) {
- if (!EDBM_op_callf(em, op, "delete geom=%S context=%i",
- &bmop, "geom_holes.out", DEL_ONLYTAGGED))
+ if (!EDBM_op_callf(
+ em, op, "delete geom=%S context=%i",
+ &bmop, "geom_holes.out", DEL_ONLYTAGGED))
{
EDBM_op_finish(em, &bmop, op, true);
return OPERATOR_CANCELLED;
@@ -5693,7 +5981,13 @@ void MESH_OT_convex_hull(wmOperatorType *ot)
join_triangle_props(ot);
}
-#endif
+#endif /* WITH_BULLET */
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Symmetrize Operator
+ * \{ */
static int mesh_symmetrize_exec(bContext *C, wmOperator *op)
{
@@ -5703,9 +5997,10 @@ static int mesh_symmetrize_exec(bContext *C, wmOperator *op)
const float thresh = RNA_float_get(op->ptr, "threshold");
- EDBM_op_init(em, &bmop, op,
- "symmetrize input=%hvef direction=%i dist=%f",
- BM_ELEM_SELECT, RNA_enum_get(op->ptr, "direction"), thresh);
+ EDBM_op_init(
+ em, &bmop, op,
+ "symmetrize input=%hvef direction=%i dist=%f",
+ BM_ELEM_SELECT, RNA_enum_get(op->ptr, "direction"), thresh);
BMO_op_exec(em->bm, &bmop);
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
@@ -5736,12 +6031,19 @@ void MESH_OT_symmetrize(struct wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "direction", rna_enum_symmetrize_direction_items,
- BMO_SYMMETRIZE_NEGATIVE_X,
- "Direction", "Which sides to copy from and to");
+ ot->prop = RNA_def_enum(
+ ot->srna, "direction", rna_enum_symmetrize_direction_items,
+ BMO_SYMMETRIZE_NEGATIVE_X,
+ "Direction", "Which sides to copy from and to");
RNA_def_float(ot->srna, "threshold", 1e-4f, 0.0f, 10.0f, "Threshold", "", 1e-5f, 0.1f);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Snap to Symmetry Operator
+ * \{ */
+
static int mesh_symmetry_snap_exec(bContext *C, wmOperator *op)
{
const float eps = 0.00001f;
@@ -5860,16 +6162,23 @@ void MESH_OT_symmetry_snap(struct wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "direction", rna_enum_symmetrize_direction_items,
- BMO_SYMMETRIZE_NEGATIVE_X,
- "Direction", "Which sides to copy from and to");
+ ot->prop = RNA_def_enum(
+ ot->srna, "direction", rna_enum_symmetrize_direction_items,
+ BMO_SYMMETRIZE_NEGATIVE_X,
+ "Direction", "Which sides to copy from and to");
RNA_def_float_distance(ot->srna, "threshold", 0.05f, 0.0f, 10.0f, "Threshold", "", 1e-4f, 1.0f);
RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0f, "Factor", "", 0.0f, 1.0f);
RNA_def_boolean(ot->srna, "use_center", true, "Center", "Snap mid verts to the axis center");
}
+/** \} */
+
#ifdef WITH_FREESTYLE
+/* -------------------------------------------------------------------- */
+/** \name Mark Edge (FreeStyle) Operator
+ * \{ */
+
static int edbm_mark_freestyle_edge_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -5935,6 +6244,12 @@ void MESH_OT_mark_freestyle_edge(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mark Face (FreeStyle) Operator
+ * \{ */
+
static int edbm_mark_freestyle_face_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -5999,4 +6314,6 @@ void MESH_OT_mark_freestyle_face(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-#endif
+/** \} */
+
+#endif /* WITH_FREESTYLE */
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index 534ca22178e..ab7e13117a0 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -29,16 +29,25 @@
#include "DNA_key_types.h"
#include "BLI_listbase.h"
+#include "BLI_array_utils.h"
+#include "BLI_alloca.h"
#include "BKE_DerivedMesh.h"
#include "BKE_context.h"
#include "BKE_key.h"
#include "BKE_mesh.h"
#include "BKE_editmesh.h"
+#include "BKE_undo_system.h"
+#include "DEG_depsgraph.h"
+
+#include "ED_object.h"
#include "ED_mesh.h"
#include "ED_util.h"
+#include "WM_types.h"
+#include "WM_api.h"
+
#define USE_ARRAY_STORE
#ifdef USE_ARRAY_STORE
@@ -60,6 +69,9 @@
# include "BLI_task.h"
#endif
+/* -------------------------------------------------------------------- */
+/** \name Undo Conversion
+ * \{ */
#ifdef USE_ARRAY_STORE
@@ -95,6 +107,8 @@ typedef struct UndoMesh {
BArrayState *mselect;
} store;
#endif /* USE_ARRAY_STORE */
+
+ size_t undo_size;
} UndoMesh;
@@ -247,7 +261,7 @@ static void um_arraystore_cd_free(BArrayCustomData *bcd)
BArrayCustomData *bcd_next = bcd->next;
const int stride = CustomData_sizeof(bcd->type);
BArrayStore *bs = BLI_array_store_at_size_get(&um_arraystore.bs_stride, stride);
- for (int i = 0; i < bcd->states_len; i++) {
+ for (int i = 0; i < bcd->states_len; i++) {
if (bcd->states[i]) {
BLI_array_store_state_remove(bs, bcd->states[i]);
}
@@ -474,28 +488,24 @@ static void um_arraystore_free(UndoMesh *um)
/* for callbacks */
/* undo simply makes copies of a bmesh */
-static void *editbtMesh_to_undoMesh(void *emv, void *obdata)
+static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key)
{
-
+ BLI_assert(BLI_array_is_zeroed(um, 1));
#ifdef USE_ARRAY_STORE_THREAD
/* changes this waits is low, but must have finished */
if (um_arraystore.task_pool) {
BLI_task_pool_work_and_wait(um_arraystore.task_pool);
}
#endif
-
- BMEditMesh *em = emv;
- Mesh *obme = obdata;
-
- UndoMesh *um = MEM_callocN(sizeof(UndoMesh), "undo Mesh");
-
/* make sure shape keys work */
- um->me.key = obme->key ? BKE_key_copy_nolib(obme->key) : NULL;
+ um->me.key = key ? BKE_key_copy_nolib(key) : NULL;
/* BM_mesh_validate(em->bm); */ /* for troubleshooting */
BM_mesh_bm_to_me(
em->bm, &um->me, (&(struct BMeshToMeshParams){
+ /* Undo code should not be manipulating 'G.main->object' hooks/vertex-parent. */
+ .calc_object_remap = false,
.cd_mask_extra = CD_MASK_SHAPE_KEYINDEX,
}));
@@ -534,13 +544,12 @@ static void *editbtMesh_to_undoMesh(void *emv, void *obdata)
return um;
}
-static void undoMesh_to_editbtMesh(void *um_v, void *em_v, void *obdata)
+static void undomesh_to_editmesh(UndoMesh *um, BMEditMesh *em, Mesh *obmesh)
{
- BMEditMesh *em = em_v, *em_tmp;
+ BMEditMesh *em_tmp;
Object *ob = em->ob;
- UndoMesh *um = um_v;
BMesh *bm;
- Key *key = ((Mesh *) obdata)->key;
+ Key *key = obmesh->key;
#ifdef USE_ARRAY_STORE
#ifdef USE_ARRAY_STORE_THREAD
@@ -613,9 +622,8 @@ static void undoMesh_to_editbtMesh(void *um_v, void *em_v, void *obdata)
#endif
}
-static void free_undo(void *um_v)
+static void undomesh_free_data(UndoMesh *um)
{
- UndoMesh *um = um_v;
Mesh *me = &um->me;
#ifdef USE_ARRAY_STORE
@@ -642,28 +650,101 @@ static void free_undo(void *um_v)
}
BKE_mesh_free(me);
- MEM_freeN(me);
}
-static void *getEditMesh(bContext *C)
+static Object *editmesh_object_from_context(bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
if (obedit && obedit->type == OB_MESH) {
Mesh *me = obedit->data;
- return me->edit_btmesh;
+ if (me->edit_btmesh != NULL) {
+ return obedit;
+ }
}
return NULL;
}
-/* and this is all the undo system needs to know */
-void undo_push_mesh(bContext *C, const char *name)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Implements ED Undo System
+ * \{ */
+
+typedef struct MeshUndoStep {
+ UndoStep step;
+ /* Use for all ID lookups (can be NULL). */
+ struct UndoIDPtrMap *id_map;
+
+ /* note: will split out into list for multi-object-editmode. */
+ UndoRefID_Object obedit_ref;
+ UndoMesh data;
+} MeshUndoStep;
+
+static bool mesh_undosys_poll(bContext *C)
{
- /* em->ob gets out of date and crashes on mesh undo,
- * this is an easy way to ensure its OK
- * though we could investigate the matter further. */
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- em->ob = obedit;
+ return editmesh_object_from_context(C) != NULL;
+}
- undo_editmode_push(C, name, getEditMesh, free_undo, undoMesh_to_editbtMesh, editbtMesh_to_undoMesh, NULL);
+static bool mesh_undosys_step_encode(struct bContext *C, UndoStep *us_p)
+{
+ MeshUndoStep *us = (MeshUndoStep *)us_p;
+ us->obedit_ref.ptr = editmesh_object_from_context(C);
+ Mesh *me = us->obedit_ref.ptr->data;
+ undomesh_from_editmesh(&us->data, me->edit_btmesh, me->key);
+ us->step.data_size = us->data.undo_size;
+ return true;
}
+
+static void mesh_undosys_step_decode(struct bContext *C, UndoStep *us_p, int UNUSED(dir))
+{
+ /* TODO(campbell): undo_system: use low-level API to set mode. */
+ ED_object_mode_set(C, OB_MODE_EDIT);
+ BLI_assert(mesh_undosys_poll(C));
+
+ MeshUndoStep *us = (MeshUndoStep *)us_p;
+ Object *obedit = us->obedit_ref.ptr;
+ Mesh *me = obedit->data;
+ BMEditMesh *em = me->edit_btmesh;
+ undomesh_to_editmesh(&us->data, em, obedit->data);
+ DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+}
+
+static void mesh_undosys_step_free(UndoStep *us_p)
+{
+ MeshUndoStep *us = (MeshUndoStep *)us_p;
+ undomesh_free_data(&us->data);
+
+ if (us->id_map != NULL) {
+ BKE_undosys_ID_map_destroy(us->id_map);
+ }
+}
+
+static void mesh_undosys_foreach_ID_ref(
+ UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+{
+ MeshUndoStep *us = (MeshUndoStep *)us_p;
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->obedit_ref));
+ if (us->id_map != NULL) {
+ BKE_undosys_ID_map_foreach_ID_ref(us->id_map, foreach_ID_ref_fn, user_data);
+ }
+}
+
+/* Export for ED_undo_sys. */
+void ED_mesh_undosys_type(UndoType *ut)
+{
+ ut->name = "Edit Mesh";
+ ut->poll = mesh_undosys_poll;
+ ut->step_encode = mesh_undosys_step_encode;
+ ut->step_decode = mesh_undosys_step_decode;
+ ut->step_free = mesh_undosys_step_free;
+
+ ut->step_foreach_ID_ref = mesh_undosys_foreach_ID_ref;
+
+ ut->mode = BKE_UNDOTYPE_MODE_STORE;
+ ut->use_context = true;
+
+ ut->step_size = sizeof(MeshUndoStep);
+}
+
+/** \} */
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index a52f12ec055..3382847c8a4 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -43,8 +43,6 @@
#include "BKE_DerivedMesh.h"
#include "BKE_context.h"
-#include "BKE_global.h"
-#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_report.h"
@@ -64,8 +62,14 @@
#include "mesh_intern.h" /* own include */
-/* mesh backup implementation. This would greatly benefit from some sort of binary diffing
- * just as the undo stack would. So leaving this as an interface for further work */
+/* -------------------------------------------------------------------- */
+/** \name Redo API
+ * \{ */
+
+/* Mesh backup implementation.
+ * This would greatly benefit from some sort of binary diffing
+ * just as the undo stack would.
+ * So leaving this as an interface for further work */
BMBackup EDBM_redo_state_store(BMEditMesh *em)
{
@@ -77,8 +81,9 @@ BMBackup EDBM_redo_state_store(BMEditMesh *em)
void EDBM_redo_state_restore(BMBackup backup, BMEditMesh *em, int recalctess)
{
BMesh *tmpbm;
- if (!em || !backup.bmcopy)
+ if (!em || !backup.bmcopy) {
return;
+ }
BM_mesh_data_free(em->bm);
tmpbm = BM_mesh_copy(backup.bmcopy);
@@ -86,8 +91,9 @@ void EDBM_redo_state_restore(BMBackup backup, BMEditMesh *em, int recalctess)
MEM_freeN(tmpbm);
tmpbm = NULL;
- if (recalctess)
+ if (recalctess) {
BKE_editmesh_tessface_calc(em);
+ }
}
void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess)
@@ -100,68 +106,21 @@ void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess)
BM_mesh_data_free(backup->bmcopy);
}
- if (backup->bmcopy)
+ if (backup->bmcopy) {
MEM_freeN(backup->bmcopy);
+ }
backup->bmcopy = NULL;
- if (recalctess && em)
+ if (recalctess && em) {
BKE_editmesh_tessface_calc(em);
-}
-
-void EDBM_mesh_normals_update(BMEditMesh *em)
-{
- BM_mesh_normals_update(em->bm);
-}
-
-void EDBM_mesh_clear(BMEditMesh *em)
-{
- /* clear bmesh */
- BM_mesh_clear(em->bm);
-
- /* free derived meshes */
- BKE_editmesh_free_derivedmesh(em);
-
- /* free tessellation data */
- em->tottri = 0;
- if (em->looptris) {
- MEM_freeN(em->looptris);
- em->looptris = NULL;
}
}
-void EDBM_stats_update(BMEditMesh *em)
-{
- const char iter_types[3] = {BM_VERTS_OF_MESH,
- BM_EDGES_OF_MESH,
- BM_FACES_OF_MESH};
-
- BMIter iter;
- BMElem *ele;
- int *tots[3];
- int i;
+/** \} */
- tots[0] = &em->bm->totvertsel;
- tots[1] = &em->bm->totedgesel;
- tots[2] = &em->bm->totfacesel;
-
- em->bm->totvertsel = em->bm->totedgesel = em->bm->totfacesel = 0;
-
- for (i = 0; i < 3; i++) {
- ele = BM_iter_new(&iter, em->bm, iter_types[i], NULL);
- for ( ; ele; ele = BM_iter_step(&iter)) {
- if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
- (*tots[i])++;
- }
- }
- }
-}
-
-DerivedMesh *EDBM_mesh_deform_dm_get(BMEditMesh *em)
-{
- return ((em->derivedFinal != NULL) &&
- (em->derivedFinal->type == DM_TYPE_EDITBMESH) &&
- (em->derivedFinal->deformedOnly != false)) ? em->derivedFinal : NULL;
-}
+/* -------------------------------------------------------------------- */
+/** \name BMesh Operator (BMO) API Wrapper
+ * \{ */
bool EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char *fmt, ...)
{
@@ -175,9 +134,10 @@ bool EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char *
va_end(list);
return false;
}
-
- if (!em->emcopy)
+
+ if (!em->emcopy) {
em->emcopy = BKE_editmesh_copy(em);
+ }
em->emcopyusers++;
va_end(list);
@@ -185,12 +145,11 @@ bool EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char *
return true;
}
-
/* returns 0 on error, 1 on success. executes and finishes a bmesh operator */
bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool do_report)
{
const char *errmsg;
-
+
BMO_op_finish(em->bm, bmop);
if (BMO_error_get(em->bm, &errmsg, NULL)) {
@@ -245,8 +204,9 @@ bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...)
return false;
}
- if (!em->emcopy)
+ if (!em->emcopy) {
em->emcopy = BKE_editmesh_copy(em);
+ }
em->emcopyusers++;
BMO_op_exec(bm, &bmop);
@@ -255,9 +215,10 @@ bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...)
return EDBM_op_finish(em, &bmop, op, true);
}
-bool EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op,
- const char *select_slot_out, const bool select_extend,
- const char *fmt, ...)
+bool EDBM_op_call_and_selectf(
+ BMEditMesh *em, wmOperator *op,
+ const char *select_slot_out, const bool select_extend,
+ const char *fmt, ...)
{
BMOpSlot *slot_select_out;
BMesh *bm = em->bm;
@@ -273,8 +234,9 @@ bool EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op,
return false;
}
- if (!em->emcopy)
+ if (!em->emcopy) {
em->emcopy = BKE_editmesh_copy(em);
+ }
em->emcopyusers++;
BMO_op_exec(bm, &bmop);
@@ -306,8 +268,9 @@ bool EDBM_op_call_silentf(BMEditMesh *em, const char *fmt, ...)
return false;
}
- if (!em->emcopy)
+ if (!em->emcopy) {
em->emcopy = BKE_editmesh_copy(em);
+ }
em->emcopyusers++;
BMO_op_exec(bm, &bmop);
@@ -316,22 +279,15 @@ bool EDBM_op_call_silentf(BMEditMesh *em, const char *fmt, ...)
return EDBM_op_finish(em, &bmop, NULL, false);
}
-void EDBM_selectmode_to_scene(bContext *C)
-{
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (!em)
- return;
+/** \} */
- scene->toolsettings->selectmode = em->selectmode;
-
- /* Request redraw of header buttons (to show new select mode) */
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, scene);
-}
+/* -------------------------------------------------------------------- */
+/** \name Edit BMesh API
+ *
+ * Make/Clear/Free functions.
+ * \{ */
-void EDBM_mesh_make(ToolSettings *ts, Object *ob, const bool add_key_index)
+void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index)
{
Mesh *me = ob->data;
BMesh *bm;
@@ -358,7 +314,7 @@ void EDBM_mesh_make(ToolSettings *ts, Object *ob, const bool add_key_index)
me->edit_btmesh = BKE_editmesh_create(bm, false);
#endif
- me->edit_btmesh->selectmode = me->edit_btmesh->bm->selectmode = ts->selectmode;
+ me->edit_btmesh->selectmode = me->edit_btmesh->bm->selectmode = select_mode;
me->edit_btmesh->mat_nr = (ob->actcol > 0) ? ob->actcol - 1 : 0;
me->edit_btmesh->ob = ob;
@@ -381,7 +337,10 @@ void EDBM_mesh_load(Object *ob)
bm->shapenr = 1;
}
- BM_mesh_bm_to_me(bm, me, (&(struct BMeshToMeshParams){0}));
+ BM_mesh_bm_to_me(
+ bm, me, (&(struct BMeshToMeshParams){
+ .calc_object_remap = true,
+ }));
#ifdef USE_TESSFACE_DEFAULT
BKE_mesh_tessface_calc(me);
@@ -410,6 +369,22 @@ void EDBM_mesh_load(Object *ob)
#endif
}
+void EDBM_mesh_clear(BMEditMesh *em)
+{
+ /* clear bmesh */
+ BM_mesh_clear(em->bm);
+
+ /* free derived meshes */
+ BKE_editmesh_free_derivedmesh(em);
+
+ /* free tessellation data */
+ em->tottri = 0;
+ if (em->looptris) {
+ MEM_freeN(em->looptris);
+ em->looptris = NULL;
+ }
+}
+
/**
* Should only be called on the active editmesh, otherwise call #BKE_editmesh_free
*/
@@ -424,6 +399,28 @@ void EDBM_mesh_free(BMEditMesh *em)
BKE_editmesh_free(em);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Selection Utilities
+ * \{ */
+
+void EDBM_selectmode_to_scene(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (!em) {
+ return;
+ }
+
+ scene->toolsettings->selectmode = em->selectmode;
+
+ /* Request redraw of header buttons (to show new select mode) */
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, scene);
+}
+
void EDBM_selectmode_flush_ex(BMEditMesh *em, const short selectmode)
{
BM_mesh_select_mode_flush_ex(em->bm, selectmode);
@@ -441,7 +438,6 @@ void EDBM_deselect_flush(BMEditMesh *em)
BM_mesh_deselect_flush(em->bm);
}
-
void EDBM_select_flush(BMEditMesh *em)
{
/* function below doesnt use. just do this to keep the values in sync */
@@ -454,9 +450,10 @@ void EDBM_select_more(BMEditMesh *em, const bool use_face_step)
BMOperator bmop;
const bool use_faces = (em->selectmode == SCE_SELECT_FACE);
- BMO_op_initf(em->bm, &bmop, BMO_FLAG_DEFAULTS,
- "region_extend geom=%hvef use_contract=%b use_faces=%b use_face_step=%b",
- BM_ELEM_SELECT, false, use_faces, use_face_step);
+ BMO_op_initf(
+ em->bm, &bmop, BMO_FLAG_DEFAULTS,
+ "region_extend geom=%hvef use_contract=%b use_faces=%b use_face_step=%b",
+ BM_ELEM_SELECT, false, use_faces, use_face_step);
BMO_op_exec(em->bm, &bmop);
/* don't flush selection in edge/vertex mode */
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false);
@@ -470,9 +467,10 @@ void EDBM_select_less(BMEditMesh *em, const bool use_face_step)
BMOperator bmop;
const bool use_faces = (em->selectmode == SCE_SELECT_FACE);
- BMO_op_initf(em->bm, &bmop, BMO_FLAG_DEFAULTS,
- "region_extend geom=%hvef use_contract=%b use_faces=%b use_face_step=%b",
- BM_ELEM_SELECT, true, use_faces, use_face_step);
+ BMO_op_initf(
+ em->bm, &bmop, BMO_FLAG_DEFAULTS,
+ "region_extend geom=%hvef use_contract=%b use_faces=%b use_face_step=%b",
+ BM_ELEM_SELECT, true, use_faces, use_face_step);
BMO_op_exec(em->bm, &bmop);
/* don't flush selection in edge/vertex mode */
BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false);
@@ -494,6 +492,12 @@ void EDBM_flag_enable_all(BMEditMesh *em, const char hflag)
BM_mesh_elem_hflag_enable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, hflag, true);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name UV Vertex Map API
+ * \{ */
+
/**
* Return a new UVVertMap from the editmesh
*/
@@ -516,7 +520,7 @@ UvVertMap *BM_uv_vert_map_create(
BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
-
+
totfaces = bm->totface;
totverts = bm->totvert;
totuv = 0;
@@ -546,7 +550,7 @@ UvVertMap *BM_uv_vert_map_create(
BKE_mesh_uv_vert_map_free(vmap);
return NULL;
}
-
+
BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, a) {
if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
float (*tf_uv)[2];
@@ -559,7 +563,7 @@ UvVertMap *BM_uv_vert_map_create(
buf->tfindex = i;
buf->f = a;
buf->separate = 0;
-
+
buf->next = vmap->vert[BM_elem_index_get(l->v)];
vmap->vert[BM_elem_index_get(l->v)] = buf;
buf++;
@@ -575,7 +579,7 @@ UvVertMap *BM_uv_vert_map_create(
}
}
}
-
+
/* sort individual uvs for each vert */
BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, a) {
UvMapVert *newvlist = NULL, *vlist = vmap->vert[a];
@@ -589,22 +593,21 @@ UvVertMap *BM_uv_vert_map_create(
newvlist = v;
efa = BM_face_at_index(bm, v->f);
-
+
l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, v->tfindex);
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uv = luv->uv;
-
+
lastv = NULL;
iterv = vlist;
while (iterv) {
next = iterv->next;
efa = BM_face_at_index(bm, iterv->f);
-
l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex);
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uv2 = luv->uv;
-
+
sub_v2_v2v2(uvdiff, uv2, uv);
if (fabsf(uvdiff[0]) < limit[0] && fabsf(uvdiff[1]) < limit[1] &&
@@ -637,13 +640,11 @@ UvVertMap *BM_uv_vert_map_create(
return vmap;
}
-
UvMapVert *BM_uv_vert_map_at_index(UvVertMap *vmap, unsigned int v)
{
return vmap->vert[v];
}
-
/* A specialized vert map used by stitch operator */
UvElementMap *BM_uv_element_map_create(
BMesh *bm,
@@ -901,26 +902,34 @@ void BM_uv_element_map_free(UvElementMap *element_map)
UvElement *BM_uv_element_get(UvElementMap *map, BMFace *efa, BMLoop *l)
{
- UvElement *element;
-
- element = map->vert[BM_elem_index_get(l->v)];
-
- for (; element; element = element->next)
- if (element->l->f == efa)
+ for (UvElement *element = map->vert[BM_elem_index_get(l->v)];
+ element;
+ element = element->next)
+ {
+ if (element->l->f == efa) {
return element;
+ }
+ }
return NULL;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Data Layer Checks
+ * \{ */
+
/* last_sel, use em->act_face otherwise get the last selected face in the editselections
* at the moment, last_sel is mainly useful for making sure the space image dosnt flicker */
BMFace *EDBM_uv_active_face_get(BMEditMesh *em, const bool sloppy, const bool selected)
{
BMFace *efa = NULL;
-
- if (!EDBM_uv_check(em))
+
+ if (!EDBM_uv_check(em)) {
return NULL;
-
+ }
+
efa = BM_mesh_active_face_get(em->bm, sloppy, selected);
if (efa) {
@@ -944,6 +953,12 @@ bool EDBM_vert_color_check(BMEditMesh *em)
return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPCOL);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mirror Cache API
+ * \{ */
+
static BMVert *cache_mirr_intptr_as_bmvert(intptr_t *index_lookup, int index)
{
intptr_t eve_i = index_lookup[index];
@@ -978,9 +993,10 @@ static BMVert *cache_mirr_intptr_as_bmvert(intptr_t *index_lookup, int index)
* \param maxdist Distance for close point test.
* \param r_index Optional array to write into, as an alternative to a customdata layer (length of total verts).
*/
-void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool use_self, const bool use_select,
- /* extra args */
- const bool use_topology, float maxdist, int *r_index)
+void EDBM_verts_mirror_cache_begin_ex(
+ BMEditMesh *em, const int axis, const bool use_self, const bool use_select,
+ /* extra args */
+ const bool use_topology, float maxdist, int *r_index)
{
Mesh *me = (Mesh *)em->ob->data;
BMesh *bm = em->bm;
@@ -1004,8 +1020,9 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool
em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, layer_id);
}
- cd_vmirr_offset = CustomData_get_n_offset(&bm->vdata, CD_PROP_INT,
- em->mirror_cdlayer - CustomData_get_layer_index(&bm->vdata, CD_PROP_INT));
+ cd_vmirr_offset = CustomData_get_n_offset(
+ &bm->vdata, CD_PROP_INT,
+ em->mirror_cdlayer - CustomData_get_layer_index(&bm->vdata, CD_PROP_INT));
bm->vdata.layers[em->mirror_cdlayer].flag |= CD_FLAG_TEMPORARY;
}
@@ -1013,7 +1030,7 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool
BM_mesh_elem_index_ensure(bm, BM_VERT);
if (use_topology) {
- ED_mesh_mirrtopo_init(me, NULL, -1, &mesh_topo_store, true);
+ ED_mesh_mirrtopo_init(me, NULL, &mesh_topo_store, true);
}
else {
tree = BLI_kdtree_new(bm->totvert);
@@ -1078,14 +1095,16 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool
}
}
-void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const int axis,
- const bool use_self, const bool use_select,
- const bool use_topology)
+void EDBM_verts_mirror_cache_begin(
+ BMEditMesh *em, const int axis,
+ const bool use_self, const bool use_select,
+ const bool use_topology)
{
- EDBM_verts_mirror_cache_begin_ex(em, axis,
- use_self, use_select,
- /* extra args */
- use_topology, BM_SEARCH_MAXDIST_MIRR, NULL);
+ EDBM_verts_mirror_cache_begin_ex(
+ em, axis,
+ use_self, use_select,
+ /* extra args */
+ use_topology, BM_SEARCH_MAXDIST_MIRR, NULL);
}
BMVert *EDBM_verts_mirror_get(BMEditMesh *em, BMVert *v)
@@ -1173,6 +1192,11 @@ void EDBM_verts_mirror_apply(BMEditMesh *em, const int sel_from, const int sel_t
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Hide/Reveal API
+ * \{ */
/* swap is 0 or 1, if 1 it hides not selected */
void EDBM_mesh_hide(BMEditMesh *em, bool swap)
@@ -1207,17 +1231,18 @@ void EDBM_mesh_hide(BMEditMesh *em, bool swap)
*/
}
-
void EDBM_mesh_reveal(BMEditMesh *em, bool select)
{
- const char iter_types[3] = {BM_VERTS_OF_MESH,
- BM_EDGES_OF_MESH,
- BM_FACES_OF_MESH};
+ const char iter_types[3] = {
+ BM_VERTS_OF_MESH,
+ BM_EDGES_OF_MESH,
+ BM_FACES_OF_MESH,
+ };
const bool sels[3] = {
- (em->selectmode & SCE_SELECT_VERTEX) != 0,
- (em->selectmode & SCE_SELECT_EDGE) != 0,
- (em->selectmode & SCE_SELECT_FACE) != 0,
+ (em->selectmode & SCE_SELECT_VERTEX) != 0,
+ (em->selectmode & SCE_SELECT_EDGE) != 0,
+ (em->selectmode & SCE_SELECT_FACE) != 0,
};
int i;
@@ -1257,6 +1282,46 @@ void EDBM_mesh_reveal(BMEditMesh *em, bool select)
EDBM_mesh_normals_update(em);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Update API
+ * \{ */
+
+void EDBM_mesh_normals_update(BMEditMesh *em)
+{
+ BM_mesh_normals_update(em->bm);
+}
+
+void EDBM_stats_update(BMEditMesh *em)
+{
+ const char iter_types[3] = {
+ BM_VERTS_OF_MESH,
+ BM_EDGES_OF_MESH,
+ BM_FACES_OF_MESH,
+ };
+
+ BMIter iter;
+ BMElem *ele;
+ int *tots[3];
+ int i;
+
+ tots[0] = &em->bm->totvertsel;
+ tots[1] = &em->bm->totedgesel;
+ tots[2] = &em->bm->totfacesel;
+
+ em->bm->totvertsel = em->bm->totedgesel = em->bm->totfacesel = 0;
+
+ for (i = 0; i < 3; i++) {
+ ele = BM_iter_new(&iter, em->bm, iter_types[i], NULL);
+ for ( ; ele; ele = BM_iter_step(&iter)) {
+ if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+ (*tots[i])++;
+ }
+ }
+ }
+}
+
/* 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)
@@ -1292,15 +1357,41 @@ void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_d
#endif
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Data Access
+ * \{ */
+
+DerivedMesh *EDBM_mesh_deform_dm_get(BMEditMesh *em)
+{
+ return ((em->derivedFinal != NULL) &&
+ (em->derivedFinal->type == DM_TYPE_EDITBMESH) &&
+ (em->derivedFinal->deformedOnly != false)) ? em->derivedFinal : NULL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Operator Helpers
+ * \{ */
+
/* poll call for mesh operators requiring a view3d context */
int EDBM_view3d_poll(bContext *C)
{
- if (ED_operator_editmesh(C) && ED_operator_view3d_active(C))
+ if (ED_operator_editmesh(C) && ED_operator_view3d_active(C)) {
return 1;
+ }
return 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name BMesh Element API
+ * \{ */
+
BMElem *EDBM_elem_from_selectmode(BMEditMesh *em, BMVert *eve, BMEdge *eed, BMFace *efa)
{
BMElem *ele = NULL;
@@ -1365,22 +1456,19 @@ BMElem *EDBM_elem_from_index_any(BMEditMesh *em, int index)
return NULL;
}
-/* -------------------------------------------------------------------- */
-/* BMBVH functions */
-// XXX
-#if 0 //BMESH_TODO: not implemented yet
-int BMBVH_VertVisible(BMBVHTree *tree, BMEdge *e, RegionView3D *r3d)
-{
+/** \} */
-}
-#endif
+/* -------------------------------------------------------------------- */
+/** \name BMesh BVH API
+ * \{ */
static BMFace *edge_ray_cast(struct BMBVHTree *tree, const float co[3], const float dir[3], float *r_hitout, BMEdge *e)
{
BMFace *f = BKE_bmbvh_ray_cast(tree, co, dir, 0.0f, NULL, r_hitout, NULL);
- if (f && BM_edge_in_face(e, f))
+ if (f && BM_edge_in_face(e, f)) {
return NULL;
+ }
return f;
}
@@ -1401,8 +1489,10 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree, BMEdge *e,
float origin[3], invmat[4][4];
float epsilon = 0.01f;
float end[3];
- const float mval_f[2] = {ar->winx / 2.0f,
- ar->winy / 2.0f};
+ const float mval_f[2] = {
+ ar->winx / 2.0f,
+ ar->winy / 2.0f,
+ };
ED_view3d_win_to_segment(depsgraph, ar, v3d, mval_f, origin, end, false);
@@ -1438,12 +1528,17 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree, BMEdge *e,
/* do three samplings: left, middle, right */
f = edge_ray_cast(tree, co1, dir1, NULL, e);
- if (f && !edge_ray_cast(tree, co2, dir2, NULL, e))
+ if (f && !edge_ray_cast(tree, co2, dir2, NULL, e)) {
return true;
- else if (f && !edge_ray_cast(tree, co3, dir3, NULL, e))
+ }
+ else if (f && !edge_ray_cast(tree, co3, dir3, NULL, e)) {
return true;
- else if (!f)
+ }
+ else if (!f) {
return true;
+ }
return false;
}
+
+/** \} */
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index 218b97d3ede..69e265f7315 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -572,7 +572,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e
obedit = base->object;
me = obedit->data;
if (me->edit_btmesh == NULL) {
- EDBM_mesh_make(scene->toolsettings, obedit, false);
+ EDBM_mesh_make(obedit, scene->toolsettings->selectmode, false);
exitmode = 1;
}
if (me->edit_btmesh == NULL)
@@ -879,9 +879,38 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator
CustomData *data = GET_CD_DATA(me, ldata);
if (me->edit_btmesh) {
+ /* Tag edges as sharp according to smooth threshold if needed, to preserve autosmooth shading. */
+ if (me->flag & ME_AUTOSMOOTH) {
+ BM_edges_sharp_from_angle_set(me->edit_btmesh->bm, me->smoothresh);
+
+ me->drawflag |= ME_DRAWSHARP;
+ }
+
BM_data_layer_add(me->edit_btmesh->bm, data, CD_CUSTOMLOOPNORMAL);
}
else {
+ /* Tag edges as sharp according to smooth threshold if needed, to preserve autosmooth shading. */
+ if (me->flag & ME_AUTOSMOOTH) {
+ float (*polynors)[3] = MEM_mallocN(sizeof(*polynors) * (size_t)me->totpoly, __func__);
+
+ BKE_mesh_calc_normals_poly(
+ me->mvert, NULL, me->totvert,
+ me->mloop, me->mpoly,
+ me->totloop, me->totpoly,
+ polynors, true);
+
+ BKE_edges_sharp_from_angle_set(
+ me->mvert, me->totvert,
+ me->medge, me->totedge,
+ me->mloop, me->totloop,
+ me->mpoly, polynors, me->totpoly,
+ me->smoothresh);
+
+ MEM_freeN(polynors);
+
+ me->drawflag |= ME_DRAWSHARP;
+ }
+
CustomData_add_layer(data, CD_CUSTOMLOOPNORMAL, CD_DEFAULT, NULL, me->totloop);
}
diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c
new file mode 100644
index 00000000000..22bfd8eedea
--- /dev/null
+++ b/source/blender/editors/mesh/mesh_mirror.c
@@ -0,0 +1,377 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Foundation, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/mesh/mesh_mirror.c
+ * \ingroup edmesh
+ *
+ * Mirror calculation for edit-mode and object mode.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_bitmap.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_DerivedMesh.h"
+#include "BLI_kdtree.h"
+#include "BKE_editmesh.h"
+
+#include "ED_mesh.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Mesh Spatial Mirror API
+ * \{ */
+
+#define KD_THRESH 0.00002f
+
+static struct { void *tree; } MirrKdStore = {NULL};
+
+/* mode is 's' start, or 'e' end, or 'u' use */
+/* if end, ob can be NULL */
+int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, DerivedMesh *dm, const float co[3], char mode)
+{
+ if (mode == 'u') { /* use table */
+ if (MirrKdStore.tree == NULL)
+ ED_mesh_mirror_spatial_table(ob, em, dm, NULL, 's');
+
+ if (MirrKdStore.tree) {
+ KDTreeNearest nearest;
+ const int i = BLI_kdtree_find_nearest(MirrKdStore.tree, co, &nearest);
+
+ if (i != -1) {
+ if (nearest.dist < KD_THRESH) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+ else if (mode == 's') { /* start table */
+ Mesh *me = ob->data;
+ const bool use_em = (!dm && em && me->edit_btmesh == em);
+ const int totvert = use_em ? em->bm->totvert : dm ? dm->getNumVerts(dm) : me->totvert;
+
+ if (MirrKdStore.tree) /* happens when entering this call without ending it */
+ ED_mesh_mirror_spatial_table(ob, em, dm, co, 'e');
+
+ MirrKdStore.tree = BLI_kdtree_new(totvert);
+
+ if (use_em) {
+ BMVert *eve;
+ BMIter iter;
+ int i;
+
+ /* this needs to be valid for index lookups later (callers need) */
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+
+ BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ BLI_kdtree_insert(MirrKdStore.tree, i, eve->co);
+ }
+ }
+ else {
+ MVert *mvert = dm ? dm->getVertArray(dm) : me->mvert;
+ int i;
+
+ for (i = 0; i < totvert; i++, mvert++) {
+ BLI_kdtree_insert(MirrKdStore.tree, i, mvert->co);
+ }
+ }
+
+ BLI_kdtree_balance(MirrKdStore.tree);
+ }
+ else if (mode == 'e') { /* end table */
+ if (MirrKdStore.tree) {
+ BLI_kdtree_free(MirrKdStore.tree);
+ MirrKdStore.tree = NULL;
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ return 0;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mesh Topology Mirror API
+ * \{ */
+
+typedef unsigned int MirrTopoHash_t;
+
+typedef struct MirrTopoVert_t {
+ MirrTopoHash_t hash;
+ int v_index;
+} MirrTopoVert_t;
+
+static int mirrtopo_hash_sort(const void *l1, const void *l2)
+{
+ if ((MirrTopoHash_t)(intptr_t)l1 > (MirrTopoHash_t)(intptr_t)l2) return 1;
+ else if ((MirrTopoHash_t)(intptr_t)l1 < (MirrTopoHash_t)(intptr_t)l2) return -1;
+ return 0;
+}
+
+static int mirrtopo_vert_sort(const void *v1, const void *v2)
+{
+ if (((MirrTopoVert_t *)v1)->hash > ((MirrTopoVert_t *)v2)->hash) return 1;
+ else if (((MirrTopoVert_t *)v1)->hash < ((MirrTopoVert_t *)v2)->hash) return -1;
+ return 0;
+}
+
+bool ED_mesh_mirrtopo_recalc_check(Mesh *me, DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store)
+{
+ const bool is_editmode = (me->edit_btmesh != NULL);
+ int totvert;
+ int totedge;
+
+ if (dm) {
+ totvert = dm->getNumVerts(dm);
+ totedge = dm->getNumEdges(dm);
+ }
+ else if (me->edit_btmesh) {
+ totvert = me->edit_btmesh->bm->totvert;
+ totedge = me->edit_btmesh->bm->totedge;
+ }
+ else {
+ totvert = me->totvert;
+ totedge = me->totedge;
+ }
+
+ if ((mesh_topo_store->index_lookup == NULL) ||
+ (mesh_topo_store->prev_is_editmode != is_editmode) ||
+ (totvert != mesh_topo_store->prev_vert_tot) ||
+ (totedge != mesh_topo_store->prev_edge_tot))
+ {
+ return true;
+ }
+ else {
+ return false;
+ }
+
+}
+
+void ED_mesh_mirrtopo_init(
+ Mesh *me, DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store,
+ const bool skip_em_vert_array_init)
+{
+ const bool is_editmode = (me->edit_btmesh != NULL);
+ MEdge *medge = NULL, *med;
+ BMEditMesh *em = dm ? NULL : me->edit_btmesh;
+
+ /* editmode*/
+ BMEdge *eed;
+ BMIter iter;
+
+ int a, last;
+ int totvert, totedge;
+ int tot_unique = -1, tot_unique_prev = -1;
+ int tot_unique_edges = 0, tot_unique_edges_prev;
+
+ MirrTopoHash_t *topo_hash = NULL;
+ MirrTopoHash_t *topo_hash_prev = NULL;
+ MirrTopoVert_t *topo_pairs;
+ MirrTopoHash_t topo_pass = 1;
+
+ intptr_t *index_lookup; /* direct access to mesh_topo_store->index_lookup */
+
+ /* reallocate if needed */
+ ED_mesh_mirrtopo_free(mesh_topo_store);
+
+ mesh_topo_store->prev_is_editmode = is_editmode;
+
+ if (em) {
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+
+ totvert = em->bm->totvert;
+ }
+ else {
+ totvert = dm ? dm->getNumVerts(dm) : me->totvert;
+ }
+
+ topo_hash = MEM_callocN(totvert * sizeof(MirrTopoHash_t), "TopoMirr");
+
+ /* Initialize the vert-edge-user counts used to detect unique topology */
+ if (em) {
+ totedge = me->edit_btmesh->bm->totedge;
+
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ const int i1 = BM_elem_index_get(eed->v1), i2 = BM_elem_index_get(eed->v2);
+ topo_hash[i1]++;
+ topo_hash[i2]++;
+ }
+ }
+ else {
+ totedge = dm ? dm->getNumEdges(dm) : me->totedge;
+ medge = dm ? dm->getEdgeArray(dm) : me->medge;
+
+ for (a = 0, med = medge; a < totedge; a++, med++) {
+ const unsigned int i1 = med->v1, i2 = med->v2;
+ topo_hash[i1]++;
+ topo_hash[i2]++;
+ }
+ }
+
+ topo_hash_prev = MEM_dupallocN(topo_hash);
+
+ tot_unique_prev = -1;
+ tot_unique_edges_prev = -1;
+ while (1) {
+ /* use the number of edges per vert to give verts unique topology IDs */
+
+ tot_unique_edges = 0;
+
+ /* This can make really big numbers, wrapping around here is fine */
+ if (em) {
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ const int i1 = BM_elem_index_get(eed->v1), i2 = BM_elem_index_get(eed->v2);
+ topo_hash[i1] += topo_hash_prev[i2] * topo_pass;
+ topo_hash[i2] += topo_hash_prev[i1] * topo_pass;
+ tot_unique_edges += (topo_hash[i1] != topo_hash[i2]);
+ }
+ }
+ else {
+ for (a = 0, med = medge; a < totedge; a++, med++) {
+ const unsigned int i1 = med->v1, i2 = med->v2;
+ topo_hash[i1] += topo_hash_prev[i2] * topo_pass;
+ topo_hash[i2] += topo_hash_prev[i1] * topo_pass;
+ tot_unique_edges += (topo_hash[i1] != topo_hash[i2]);
+ }
+ }
+ memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert);
+
+ /* sort so we can count unique values */
+ qsort(topo_hash_prev, totvert, sizeof(MirrTopoHash_t), mirrtopo_hash_sort);
+
+ tot_unique = 1; /* account for skiping the first value */
+ for (a = 1; a < totvert; a++) {
+ if (topo_hash_prev[a - 1] != topo_hash_prev[a]) {
+ tot_unique++;
+ }
+ }
+
+ if ((tot_unique <= tot_unique_prev) && (tot_unique_edges <= tot_unique_edges_prev)) {
+ /* Finish searching for unique values when 1 loop dosnt give a
+ * higher number of unique values compared to the previous loop */
+ break;
+ }
+ else {
+ tot_unique_prev = tot_unique;
+ tot_unique_edges_prev = tot_unique_edges;
+ }
+ /* Copy the hash calculated this iter, so we can use them next time */
+ memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert);
+
+ topo_pass++;
+ }
+
+ /* Hash/Index pairs are needed for sorting to find index pairs */
+ topo_pairs = MEM_callocN(sizeof(MirrTopoVert_t) * totvert, "MirrTopoPairs");
+
+ /* since we are looping through verts, initialize these values here too */
+ index_lookup = MEM_mallocN(totvert * sizeof(*index_lookup), "mesh_topo_lookup");
+
+ if (em) {
+ if (skip_em_vert_array_init == false) {
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ }
+ }
+
+ for (a = 0; a < totvert; a++) {
+ topo_pairs[a].hash = topo_hash[a];
+ topo_pairs[a].v_index = a;
+
+ /* initialize lookup */
+ index_lookup[a] = -1;
+ }
+
+ qsort(topo_pairs, totvert, sizeof(MirrTopoVert_t), mirrtopo_vert_sort);
+
+ last = 0;
+
+ /* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2,
+ * but you cant ever access the last 'a' index of MirrTopoPairs */
+ if (em) {
+ BMVert **vtable = em->bm->vtable;
+ for (a = 1; a <= totvert; a++) {
+ /* printf("I %d %ld %d\n", (a - last), MirrTopoPairs[a].hash, MirrTopoPairs[a].v_indexs); */
+ if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) {
+ const int match_count = a - last;
+ if (match_count == 2) {
+ const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index;
+ index_lookup[j] = (intptr_t)vtable[k];
+ index_lookup[k] = (intptr_t)vtable[j];
+ }
+ else if (match_count == 1) {
+ /* Center vertex. */
+ const int j = topo_pairs[a - 1].v_index;
+ index_lookup[j] = (intptr_t)vtable[j];
+ }
+ last = a;
+ }
+ }
+ }
+ else {
+ /* same as above, for mesh */
+ for (a = 1; a <= totvert; a++) {
+ if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) {
+ const int match_count = a - last;
+ if (match_count == 2) {
+ const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index;
+ index_lookup[j] = k;
+ index_lookup[k] = j;
+ }
+ else if (match_count == 1) {
+ /* Center vertex. */
+ const int j = topo_pairs[a - 1].v_index;
+ index_lookup[j] = j;
+ }
+ last = a;
+ }
+ }
+ }
+
+ MEM_freeN(topo_pairs);
+ topo_pairs = NULL;
+
+ MEM_freeN(topo_hash);
+ MEM_freeN(topo_hash_prev);
+
+ mesh_topo_store->index_lookup = index_lookup;
+ mesh_topo_store->prev_vert_tot = totvert;
+ mesh_topo_store->prev_edge_tot = totedge;
+}
+
+void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store)
+{
+ if (mesh_topo_store->index_lookup) {
+ MEM_freeN(mesh_topo_store->index_lookup);
+ }
+ mesh_topo_store->index_lookup = NULL;
+ mesh_topo_store->prev_vert_tot = -1;
+ mesh_topo_store->prev_edge_tot = -1;
+}
+
+/** \} */
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index dd1fbc36d8a..531a26a66a8 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -42,12 +42,11 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
-
-#include "BLI_kdtree.h"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_DerivedMesh.h"
@@ -57,6 +56,7 @@
#include "BKE_mesh.h"
#include "BKE_material.h"
#include "BKE_object.h"
+#include "BKE_object_deform.h"
#include "BKE_report.h"
#include "BKE_editmesh.h"
#include "BKE_multires.h"
@@ -79,7 +79,7 @@
* return 0 if no join is made (error) and 1 if the join is done */
static void join_mesh_single(
- bContext *C, Main *bmain, Scene *scene,
+ const EvaluationContext *eval_ctx, Main *bmain, Scene *scene,
Object *ob_dst, Object *ob_src, float imat[4][4],
MVert **mvert_pp, MEdge **medge_pp, MLoop **mloop_pp, MPoly **mpoly_pp,
CustomData *vdata, CustomData *edata, CustomData *ldata, CustomData *pdata,
@@ -88,7 +88,6 @@ static void join_mesh_single(
Material **matar, int *matmap, int totcol,
int *vertofs, int *edgeofs, int *loopofs, int *polyofs)
{
- EvaluationContext eval_ctx;
int a, b;
Mesh *me = ob_src->data;
@@ -97,8 +96,6 @@ static void join_mesh_single(
MLoop *mloop = *mloop_pp;
MPoly *mpoly = *mpoly_pp;
- CTX_data_eval_ctx(C, &eval_ctx);
-
if (me->totvert) {
/* merge customdata flag */
((Mesh *)ob_dst->data)->cd_flag |= me->cd_flag;
@@ -116,21 +113,12 @@ static void join_mesh_single(
BLI_assert(dvert != NULL);
/* Build src to merged mapping of vgroup indices. */
- bDeformGroup *dg_src;
- int *vgroup_index_map = alloca(sizeof(*vgroup_index_map) * BLI_listbase_count(&ob_src->defbase));
- bool is_vgroup_remap_needed = false;
-
- for (dg_src = ob_src->defbase.first, b = 0; dg_src; dg_src = dg_src->next, b++) {
- vgroup_index_map[b] = defgroup_name_index(ob_dst, dg_src->name);
- is_vgroup_remap_needed = is_vgroup_remap_needed || (vgroup_index_map[b] != b);
- }
-
- if (is_vgroup_remap_needed) {
- for (a = 0; a < me->totvert; a++) {
- for (b = 0; b < dvert[a].totweight; b++) {
- dvert[a].dw[b].def_nr = vgroup_index_map[dvert_src[a].dw[b].def_nr];
- }
- }
+ int *vgroup_index_map;
+ int vgroup_index_map_len;
+ vgroup_index_map = BKE_object_defgroup_index_map_create(ob_src, ob_dst, &vgroup_index_map_len);
+ BKE_object_defgroup_index_map_apply(dvert, me->totvert, vgroup_index_map, vgroup_index_map_len);
+ if (vgroup_index_map != NULL) {
+ MEM_freeN(vgroup_index_map);
}
}
@@ -219,7 +207,7 @@ static void join_mesh_single(
if (ob_src != ob_dst) {
MultiresModifierData *mmd;
- multiresModifier_prepare_join(&eval_ctx, scene, ob_src, ob_dst);
+ multiresModifier_prepare_join(eval_ctx, scene, ob_src, ob_dst);
if ((mmd = get_multires_modifier(scene, ob_src, true))) {
ED_object_iter_other(bmain, ob_src, true,
@@ -293,7 +281,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
bDeformGroup *dg, *odg;
CustomData vdata, edata, fdata, ldata, pdata;
- if (scene->obedit) {
+ if (ob->mode & OB_MODE_EDIT) {
BKE_report(op->reports, RPT_WARNING, "Cannot join while in edit mode");
return OPERATOR_CANCELLED;
}
@@ -303,7 +291,10 @@ int join_mesh_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_WARNING, "Active object is not a mesh");
return OPERATOR_CANCELLED;
}
-
+
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* count & check */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
@@ -498,7 +489,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
* active mesh will remain first ones in new result of the merge, in same order for CD layers, etc. See also T50084.
*/
join_mesh_single(
- C, bmain, scene,
+ &eval_ctx, bmain, scene,
ob, ob, imat,
&mvert, &medge, &mloop, &mpoly,
&vdata, &edata, &ldata, &pdata,
@@ -515,7 +506,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/* only join if this is a mesh */
if (base->object->type == OB_MESH) {
join_mesh_single(
- C, bmain, scene,
+ &eval_ctx, bmain, scene,
ob, base->object, imat,
&mvert, &medge, &mloop, &mpoly,
&vdata, &edata, &ldata, &pdata,
@@ -567,12 +558,10 @@ int join_mesh_exec(bContext *C, wmOperator *op)
if (ma)
id_us_min(&ma->id);
}
- if (ob->mat) MEM_freeN(ob->mat);
- if (ob->matbits) MEM_freeN(ob->matbits);
- if (me->mat) MEM_freeN(me->mat);
- ob->mat = me->mat = NULL;
- ob->matbits = NULL;
-
+ MEM_SAFE_FREE(ob->mat);
+ MEM_SAFE_FREE(ob->matbits);
+ MEM_SAFE_FREE(me->mat);
+
if (totcol) {
me->mat = matar;
ob->mat = MEM_callocN(sizeof(*ob->mat) * totcol, "join obmatar");
@@ -687,84 +676,6 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-/* -------------------------------------------------------------------- */
-/* Mesh Mirror (Spatial) */
-
-/** \name Mesh Spatial Mirror API
- * \{ */
-
-#define KD_THRESH 0.00002f
-
-static struct { void *tree; } MirrKdStore = {NULL};
-
-/* mode is 's' start, or 'e' end, or 'u' use */
-/* if end, ob can be NULL */
-int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, DerivedMesh *dm, const float co[3], char mode)
-{
- if (mode == 'u') { /* use table */
- if (MirrKdStore.tree == NULL)
- ED_mesh_mirror_spatial_table(ob, em, dm, NULL, 's');
-
- if (MirrKdStore.tree) {
- KDTreeNearest nearest;
- const int i = BLI_kdtree_find_nearest(MirrKdStore.tree, co, &nearest);
-
- if (i != -1) {
- if (nearest.dist < KD_THRESH) {
- return i;
- }
- }
- }
- return -1;
- }
- else if (mode == 's') { /* start table */
- Mesh *me = ob->data;
- const bool use_em = (!dm && em && me->edit_btmesh == em);
- const int totvert = use_em ? em->bm->totvert : dm ? dm->getNumVerts(dm) : me->totvert;
-
- if (MirrKdStore.tree) /* happens when entering this call without ending it */
- ED_mesh_mirror_spatial_table(ob, em, dm, co, 'e');
-
- MirrKdStore.tree = BLI_kdtree_new(totvert);
-
- if (use_em) {
- BMVert *eve;
- BMIter iter;
- int i;
-
- /* this needs to be valid for index lookups later (callers need) */
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
-
- BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
- BLI_kdtree_insert(MirrKdStore.tree, i, eve->co);
- }
- }
- else {
- MVert *mvert = dm ? dm->getVertArray(dm) : me->mvert;
- int i;
-
- for (i = 0; i < totvert; i++, mvert++) {
- BLI_kdtree_insert(MirrKdStore.tree, i, mvert->co);
- }
- }
-
- BLI_kdtree_balance(MirrKdStore.tree);
- }
- else if (mode == 'e') { /* end table */
- if (MirrKdStore.tree) {
- BLI_kdtree_free(MirrKdStore.tree);
- MirrKdStore.tree = NULL;
- }
- }
- else {
- BLI_assert(0);
- }
-
- return 0;
-}
-
-/** \} */
-
/* -------------------------------------------------------------------- */
/* Mesh Mirror (Topology) */
@@ -777,15 +688,16 @@ static MirrTopoStore_t mesh_topo_store = {NULL, -1. - 1, -1};
/* mode is 's' start, or 'e' end, or 'u' use */
/* if end, ob can be NULL */
/* note, is supposed return -1 on error, which callers are currently checking for, but is not used so far */
-int ED_mesh_mirror_topo_table(Object *ob, DerivedMesh *dm, char mode)
+int ED_mesh_mirror_topo_table(
+ Object *ob, DerivedMesh *dm, char mode)
{
if (mode == 'u') { /* use table */
- if (ED_mesh_mirrtopo_recalc_check(ob->data, dm, ob->mode, &mesh_topo_store)) {
+ if (ED_mesh_mirrtopo_recalc_check(ob->data, dm, &mesh_topo_store)) {
ED_mesh_mirror_topo_table(ob, dm, 's');
}
}
else if (mode == 's') { /* start table */
- ED_mesh_mirrtopo_init(ob->data, dm, ob->mode, &mesh_topo_store, false);
+ ED_mesh_mirrtopo_init(ob->data, dm, &mesh_topo_store, false);
}
else if (mode == 'e') { /* end table */
ED_mesh_mirrtopo_free(&mesh_topo_store);
@@ -1106,7 +1018,7 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int
return false;
CTX_data_eval_ctx(C, &eval_ctx);
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
if (size) {
/* sample rect to increase chances of selecting, so that when clicking
@@ -1277,7 +1189,7 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int
if (!me || me->totvert == 0)
return false;
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
if (use_zbuf) {
if (size > 0) {
diff --git a/source/blender/editors/metaball/CMakeLists.txt b/source/blender/editors/metaball/CMakeLists.txt
index 89ba942ac36..73f80774716 100644
--- a/source/blender/editors/metaball/CMakeLists.txt
+++ b/source/blender/editors/metaball/CMakeLists.txt
@@ -35,6 +35,7 @@ set(INC_SYS
)
set(SRC
+ editmball_undo.c
mball_edit.c
mball_ops.c
diff --git a/source/blender/editors/metaball/editmball_undo.c b/source/blender/editors/metaball/editmball_undo.c
new file mode 100644
index 00000000000..cc461c0c365
--- /dev/null
+++ b/source/blender/editors/metaball/editmball_undo.c
@@ -0,0 +1,200 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/metaball/editmball_undo.c
+ * \ingroup edmeta
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+#include "BLI_array_utils.h"
+
+#include "DNA_defs.h"
+#include "DNA_meta_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_context.h"
+#include "BKE_undo_system.h"
+
+#include "DEG_depsgraph.h"
+
+#include "ED_object.h"
+#include "ED_mball.h"
+#include "ED_util.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Undo Conversion
+ * \{ */
+
+typedef struct UndoMBall {
+ ListBase editelems;
+ int lastelem_index;
+ size_t undo_size;
+} UndoMBall;
+
+/* free all MetaElems from ListBase */
+static void freeMetaElemlist(ListBase *lb)
+{
+ MetaElem *ml;
+
+ if (lb == NULL) {
+ return;
+ }
+
+ while ((ml = BLI_pophead(lb))) {
+ MEM_freeN(ml);
+ }
+}
+
+static void undomball_to_editmball(UndoMBall *umb, MetaBall *mb)
+{
+ freeMetaElemlist(mb->editelems);
+ mb->lastelem = NULL;
+
+ /* copy 'undo' MetaElems to 'edit' MetaElems */
+ int index = 0;
+ for (MetaElem *ml_undo = umb->editelems.first; ml_undo; ml_undo = ml_undo->next, index += 1) {
+ MetaElem *ml_edit = MEM_dupallocN(ml_undo);
+ BLI_addtail(mb->editelems, ml_edit);
+ if (index == umb->lastelem_index) {
+ mb->lastelem = ml_edit;
+ }
+ }
+}
+
+static void *editmball_from_undomball(UndoMBall *umb, MetaBall *mb)
+{
+ BLI_assert(BLI_array_is_zeroed(umb, 1));
+
+ /* allocate memory for undo ListBase */
+ umb->lastelem_index = -1;
+
+ /* copy contents of current ListBase to the undo ListBase */
+ int index = 0;
+ for (MetaElem *ml_edit = mb->editelems->first; ml_edit; ml_edit = ml_edit->next, index += 1) {
+ MetaElem *ml_undo = MEM_dupallocN(ml_edit);
+ BLI_addtail(&umb->editelems, ml_undo);
+ if (ml_edit == mb->lastelem) {
+ umb->lastelem_index = index;
+ }
+ umb->undo_size += sizeof(MetaElem);
+ }
+
+ return umb;
+}
+
+/* free undo ListBase of MetaElems */
+static void undomball_free_data(UndoMBall *umb)
+{
+ freeMetaElemlist(&umb->editelems);
+}
+
+static Object *editmball_object_from_context(bContext *C)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_MBALL) {
+ MetaBall *mb = obedit->data;
+ if (mb->editelems != NULL) {
+ return obedit;
+ }
+ }
+ return NULL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Implements ED Undo System
+ * \{ */
+
+typedef struct MBallUndoStep {
+ UndoStep step;
+ /* note: will split out into list for multi-object-editmode. */
+ UndoRefID_Object obedit_ref;
+ UndoMBall data;
+} MBallUndoStep;
+
+static bool mball_undosys_poll(bContext *C)
+{
+ return editmball_object_from_context(C) != NULL;
+}
+
+static bool mball_undosys_step_encode(struct bContext *C, UndoStep *us_p)
+{
+ MBallUndoStep *us = (MBallUndoStep *)us_p;
+ us->obedit_ref.ptr = editmball_object_from_context(C);
+ MetaBall *mb = us->obedit_ref.ptr->data;
+ editmball_from_undomball(&us->data, mb);
+ us->step.data_size = us->data.undo_size;
+ return true;
+}
+
+static void mball_undosys_step_decode(struct bContext *C, UndoStep *us_p, int UNUSED(dir))
+{
+ ED_object_mode_set(C, OB_MODE_EDIT);
+
+ MBallUndoStep *us = (MBallUndoStep *)us_p;
+ Object *obedit = us->obedit_ref.ptr;
+ MetaBall *mb = obedit->data;
+ undomball_to_editmball(&us->data, mb);
+ DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+}
+
+static void mball_undosys_step_free(UndoStep *us_p)
+{
+ MBallUndoStep *us = (MBallUndoStep *)us_p;
+ undomball_free_data(&us->data);
+}
+
+static void mball_undosys_foreach_ID_ref(
+ UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+{
+ MBallUndoStep *us = (MBallUndoStep *)us_p;
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->obedit_ref));
+}
+
+/* Export for ED_undo_sys. */
+void ED_mball_undosys_type(UndoType *ut)
+{
+ ut->name = "Edit MBall";
+ ut->poll = mball_undosys_poll;
+ ut->step_encode = mball_undosys_step_encode;
+ ut->step_decode = mball_undosys_step_decode;
+ ut->step_free = mball_undosys_step_free;
+
+ ut->step_foreach_ID_ref = mball_undosys_foreach_ID_ref;
+
+ ut->mode = BKE_UNDOTYPE_MODE_STORE;
+ ut->use_context = true;
+
+ ut->step_size = sizeof(MBallUndoStep);
+
+}
+
+/** \} */
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index 935f1a5ea4a..6dd16b52387 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -29,7 +29,6 @@
* \ingroup edmeta
*/
-
#include <math.h>
#include <string.h>
@@ -56,7 +55,6 @@
#include "ED_mball.h"
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "ED_util.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -598,7 +596,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
rcti rect;
CTX_data_eval_ctx(C, &eval_ctx);
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
BLI_rcti_init_pt_radius(&rect, mval, 12);
@@ -668,94 +666,3 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
}
-/* ************* undo for MetaBalls ************* */
-
-typedef struct UndoMBall {
- ListBase editelems;
- int lastelem_index;
-} UndoMBall;
-
-/* free all MetaElems from ListBase */
-static void freeMetaElemlist(ListBase *lb)
-{
- MetaElem *ml;
-
- if (lb == NULL) return;
-
- while ((ml = BLI_pophead(lb))) {
- MEM_freeN(ml);
- }
-}
-
-
-static void undoMball_to_editMball(void *umb_v, void *mb_v, void *UNUSED(obdata))
-{
- MetaBall *mb = mb_v;
- UndoMBall *umb = umb_v;
-
- freeMetaElemlist(mb->editelems);
- mb->lastelem = NULL;
-
- /* copy 'undo' MetaElems to 'edit' MetaElems */
- int index = 0;
- for (MetaElem *ml_undo = umb->editelems.first; ml_undo; ml_undo = ml_undo->next, index += 1) {
- MetaElem *ml_edit = MEM_dupallocN(ml_undo);
- BLI_addtail(mb->editelems, ml_edit);
- if (index == umb->lastelem_index) {
- mb->lastelem = ml_edit;
- }
- }
-
-}
-
-static void *editMball_to_undoMball(void *mb_v, void *UNUSED(obdata))
-{
- MetaBall *mb = mb_v;
- UndoMBall *umb;
-
- /* allocate memory for undo ListBase */
- umb = MEM_callocN(sizeof(UndoMBall), __func__);
- umb->lastelem_index = -1;
-
- /* copy contents of current ListBase to the undo ListBase */
- int index = 0;
- for (MetaElem *ml_edit = mb->editelems->first; ml_edit; ml_edit = ml_edit->next, index += 1) {
- MetaElem *ml_undo = MEM_dupallocN(ml_edit);
- BLI_addtail(&umb->editelems, ml_undo);
- if (ml_edit == mb->lastelem) {
- umb->lastelem_index = index;
- }
- }
-
- return umb;
-}
-
-/* free undo ListBase of MetaElems */
-static void free_undoMball(void *umb_v)
-{
- UndoMBall *umb = umb_v;
-
- freeMetaElemlist(&umb->editelems);
- MEM_freeN(umb);
-}
-
-static MetaBall *metaball_get_obdata(Object *ob)
-{
- if (ob && ob->type == OB_MBALL) {
- return ob->data;
- }
- return NULL;
-}
-
-
-static void *get_data(bContext *C)
-{
- Object *obedit = CTX_data_edit_object(C);
- return metaball_get_obdata(obedit);
-}
-
-/* this is undo system for MetaBalls */
-void undo_push_mball(bContext *C, const char *name)
-{
- undo_editmode_push(C, name, get_data, free_undoMball, undoMball_to_editMball, editMball_to_undoMball, NULL);
-}
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index 8050508983b..646b8137b2d 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -50,8 +50,8 @@ set(SRC
object_facemap_ops.c
object_group.c
object_hook.c
- object_lattice.c
object_lod.c
+ object_modes.c
object_modifier.c
object_ops.c
object_random.c
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 89b131fa340..3a12d56d9c2 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -43,8 +43,8 @@
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
-#include "DNA_object_fluidsim.h"
-#include "DNA_object_force.h"
+#include "DNA_object_fluidsim_types.h"
+#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
#include "DNA_lightprobe_types.h"
#include "DNA_scene_types.h"
@@ -434,7 +434,7 @@ Object *ED_object_add_type(
/* for as long scene has editmode... */
if (CTX_data_edit_object(C))
- ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); /* freedata, and undo */
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR | EM_DO_UNDO); /* freedata, and undo */
/* deselects all, sets scene->basact */
ob = BKE_object_add(bmain, scene, view_layer, type, name);
@@ -1194,8 +1194,8 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op)
{
/* create new data for NLA hierarchy */
AnimData *adt = BKE_animdata_add_id(&ob->id);
- NlaTrack *nlt = add_nlatrack(adt, NULL);
- NlaStrip *strip = add_nla_soundstrip(scene, ob->data);
+ NlaTrack *nlt = BKE_nlatrack_add(adt, NULL);
+ NlaStrip *strip = BKE_nla_add_soundstrip(scene, ob->data);
strip->start = CFRA;
strip->end += strip->start;
@@ -1696,7 +1696,7 @@ static void curvetomesh(EvaluationContext *eval_ctx, Main *bmain, Scene *scene,
BKE_mesh_from_nurbs(ob); /* also does users */
if (ob->type == OB_MESH) {
- BKE_object_free_modifiers(ob);
+ BKE_object_free_modifiers(ob, 0);
/* Game engine defaults for mesh objects */
ob->body_type = OB_BODY_TYPE_STATIC;
@@ -1710,7 +1710,7 @@ static int convert_poll(bContext *C)
Base *base_act = CTX_data_active_base(C);
Object *obact = base_act ? base_act->object : NULL;
- return (!ID_IS_LINKED(scene) && obact && scene->obedit != obact &&
+ return (!ID_IS_LINKED(scene) && obact && (BKE_object_is_in_editmode(obact) == false) &&
(base_act->flag & BASE_SELECTED) && !ID_IS_LINKED(obact));
}
@@ -1756,7 +1756,7 @@ static int convert_exec(bContext *C, wmOperator *op)
/* don't forget multiple users! */
{
- FOREACH_SCENE_OBJECT(scene, ob)
+ FOREACH_SCENE_OBJECT_BEGIN(scene, ob)
{
ob->flag &= ~OB_DONE;
@@ -1776,7 +1776,7 @@ static int convert_exec(bContext *C, wmOperator *op)
}
}
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
}
ListBase selected_editable_bases = CTX_data_collection_get(C, "selected_editable_bases");
@@ -1806,7 +1806,7 @@ static int convert_exec(bContext *C, wmOperator *op)
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
uint64_t customdata_mask_prev = scene->customdata_mask;
scene->customdata_mask |= CD_MASK_MESH;
- BKE_scene_graph_update_tagged(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
scene->customdata_mask = customdata_mask_prev;
}
@@ -1825,7 +1825,7 @@ static int convert_exec(bContext *C, wmOperator *op)
/* When 2 objects with linked data are selected, converting both
* would keep modifiers on all but the converted object [#26003] */
if (ob->type == OB_MESH) {
- BKE_object_free_modifiers(ob); /* after derivedmesh calls! */
+ BKE_object_free_modifiers(ob, 0); /* after derivedmesh calls! */
}
}
}
@@ -1850,7 +1850,7 @@ static int convert_exec(bContext *C, wmOperator *op)
BKE_mesh_to_curve(&eval_ctx, scene, newob);
if (newob->type == OB_CURVE) {
- BKE_object_free_modifiers(newob); /* after derivedmesh calls! */
+ BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
ED_rigidbody_object_remove(bmain, scene, newob);
}
}
@@ -1883,7 +1883,7 @@ static int convert_exec(bContext *C, wmOperator *op)
/* re-tessellation is called by DM_to_mesh */
- BKE_object_free_modifiers(newob); /* after derivedmesh calls! */
+ BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
}
else if (ob->type == OB_FONT) {
ob->flag |= OB_DONE;
@@ -2046,7 +2046,7 @@ static int convert_exec(bContext *C, wmOperator *op)
if (!keep_original) {
if (mballConverted) {
- FOREACH_SCENE_OBJECT(scene, ob_mball)
+ FOREACH_SCENE_OBJECT_BEGIN(scene, ob_mball)
{
if (ob_mball->type == OB_MBALL) {
if (ob_mball->flag & OB_DONE) {
@@ -2059,7 +2059,7 @@ static int convert_exec(bContext *C, wmOperator *op)
}
}
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
}
/* delete object should renew depsgraph */
@@ -2560,10 +2560,9 @@ static int join_poll(bContext *C)
static int join_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
- if (scene->obedit) {
+ if (ob->mode & OB_MODE_EDIT) {
BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode");
return OPERATOR_CANCELLED;
}
@@ -2614,10 +2613,9 @@ static int join_shapes_poll(bContext *C)
static int join_shapes_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
- if (scene->obedit) {
+ if (ob->mode & OB_MODE_EDIT) {
BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode");
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index 3efb6253f6f..a38b9959dab 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -576,6 +576,7 @@ typedef struct BakeRender {
Render *re;
Main *main;
Scene *scene;
+ ViewLayer *view_layer;
struct Object *actob;
int result, ready;
@@ -625,6 +626,7 @@ static void init_bake_internal(BakeRender *bkr, bContext *C)
bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL; /* can be NULL */
bkr->main = CTX_data_main(C);
bkr->scene = scene;
+ bkr->view_layer = view_layer;
bkr->actob = (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT(view_layer) : NULL;
bkr->re = RE_NewRender("_Bake View_");
@@ -730,7 +732,7 @@ static void bake_startjob(void *bkv, short *stop, short *do_update, float *progr
RE_test_break_cb(bkr->re, NULL, thread_break);
G.is_break = false; /* BKE_blender_test_break uses this global */
- RE_Database_Baking(bkr->re, bmain, scene, scene->lay, scene->r.bake_mode, bkr->actob);
+ RE_Database_Baking(bkr->re, bmain, scene, bkr->view_layer, scene->lay, scene->r.bake_mode, bkr->actob);
/* baking itself is threaded, cannot use test_break in threads. we also update optional imagewindow */
bkr->result = RE_bake_shade_all_selected(bkr->re, scene->r.bake_mode, bkr->actob, bkr->do_update, bkr->progress);
@@ -838,7 +840,6 @@ static int bake_image_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
int result = OPERATOR_CANCELLED;
if (is_multires_bake(scene)) {
@@ -858,12 +859,13 @@ static int bake_image_exec(bContext *C, wmOperator *op)
RE_test_break_cb(bkr.re, NULL, thread_break);
G.is_break = false; /* BKE_blender_test_break uses this global */
- RE_Database_Baking(bkr.re, bmain, scene, scene->lay, scene->r.bake_mode, (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT(view_layer) : NULL);
+ RE_Database_Baking(bkr.re, bmain, scene, bkr.view_layer, scene->lay, scene->r.bake_mode,
+ (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT(bkr.view_layer) : NULL);
/* baking itself is threaded, cannot use test_break in threads */
- BLI_init_threads(&threads, do_bake_render, 1);
+ BLI_threadpool_init(&threads, do_bake_render, 1);
bkr.ready = 0;
- BLI_insert_thread(&threads, &bkr);
+ BLI_threadpool_insert(&threads, &bkr);
while (bkr.ready == 0) {
PIL_sleep_ms(50);
@@ -874,7 +876,7 @@ static int bake_image_exec(bContext *C, wmOperator *op)
if (!G.background)
BKE_blender_test_break();
}
- BLI_end_threads(&threads);
+ BLI_threadpool_end(&threads);
if (bkr.result == BAKE_RESULT_NO_OBJECTS)
BKE_report(op->reports, RPT_ERROR, "No valid images found to bake to");
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 0174a307c16..40a49df1657 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -56,9 +56,11 @@
#include "BKE_report.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
+#include "BKE_scene.h"
#include "BKE_screen.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
#include "RE_engine.h"
#include "RE_pipeline.h"
@@ -84,8 +86,8 @@ static void bake_set_props(wmOperator *op, Scene *scene);
typedef struct BakeAPIRender {
Object *ob;
Main *main;
- Depsgraph *depsgraph;
Scene *scene;
+ ViewLayer *view_layer;
ReportList *reports;
ListBase selected_objects;
@@ -623,10 +625,9 @@ static size_t initialize_internal_images(BakeImages *bake_images, ReportList *re
/* create new mesh with edit mode changes and modifiers applied */
static Mesh *bake_mesh_new_from_object(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Object *ob)
{
- if (ob->mode & OB_MODE_EDIT)
- ED_object_editmode_load(ob);
+ ED_object_editmode_load(ob);
- Mesh *me = BKE_mesh_new_from_object(eval_ctx, bmain, scene, ob, 1, 2, 0, 0);
+ Mesh *me = BKE_mesh_new_from_object(eval_ctx, bmain, scene, ob, 1, 0, 0);
if (me->flag & ME_AUTOSMOOTH) {
BKE_mesh_split_faces(me, true);
}
@@ -635,7 +636,8 @@ static Mesh *bake_mesh_new_from_object(EvaluationContext *eval_ctx, Main *bmain,
}
static int bake(
- Render *re, Main *bmain, Depsgraph *graph, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports,
+ Render *re, Main *bmain, Scene *scene, ViewLayer *view_layer, Object *ob_low, ListBase *selected_objects,
+ ReportList *reports,
const eScenePassType pass_type, const int pass_filter, const int margin,
const eBakeSaveMode save_mode, const bool is_clear, const bool is_split_materials,
const bool is_automatic_name, const bool is_selected_to_active, const bool is_cage,
@@ -643,6 +645,10 @@ static int bake(
const char *custom_cage, const char *filepath, const int width, const int height,
const char *identifier, ScrArea *sa, const char *uv_layer)
{
+ EvaluationContext *eval_ctx = DEG_evaluation_context_new(DAG_EVAL_RENDER);
+ Depsgraph *depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
+ DEG_evaluation_context_init_from_view_layer_for_render(eval_ctx, depsgraph, scene, view_layer);
+
int op_result = OPERATOR_CANCELLED;
bool ok = false;
@@ -674,7 +680,7 @@ static int bake(
size_t num_pixels;
int tot_materials;
- RE_bake_engine_set_engine_parameters(re, bmain, graph, scene);
+ RE_bake_engine_set_engine_parameters(re, bmain, scene);
if (!RE_bake_has_engine(re)) {
BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
@@ -784,8 +790,12 @@ static int bake(
}
}
+ /* Make sure depsgraph is up to date. */
+ DEG_graph_build_from_view_layer(depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
+
/* get the mesh as it arrives in the renderer */
- me_low = bake_mesh_new_from_object(RE_GetEvalCtx(re), bmain, scene, ob_low);
+ me_low = bake_mesh_new_from_object(eval_ctx, bmain, scene, ob_low);
/* populate the pixel array with the face data */
if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false)
@@ -800,7 +810,7 @@ static int bake(
/* prepare cage mesh */
if (ob_cage) {
- me_cage = bake_mesh_new_from_object(RE_GetEvalCtx(re), bmain, scene, ob_cage);
+ me_cage = bake_mesh_new_from_object(eval_ctx, bmain, scene, ob_cage);
if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
BKE_report(reports, RPT_ERROR,
"Invalid cage object, the cage mesh must have the same number "
@@ -832,7 +842,7 @@ static int bake(
ob_low->modifiers = modifiers_tmp;
/* get the cage mesh as it arrives in the renderer */
- me_cage = bake_mesh_new_from_object(RE_GetEvalCtx(re), bmain, scene, ob_low);
+ me_cage = bake_mesh_new_from_object(eval_ctx, bmain, scene, ob_low);
RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
}
@@ -858,7 +868,7 @@ static int bake(
tmd->quad_method = MOD_TRIANGULATE_QUAD_FIXED;
tmd->ngon_method = MOD_TRIANGULATE_NGON_EARCLIP;
- highpoly[i].me = bake_mesh_new_from_object(RE_GetEvalCtx(re), bmain, scene, highpoly[i].ob);
+ highpoly[i].me = bake_mesh_new_from_object(eval_ctx, bmain, scene, highpoly[i].ob);
highpoly[i].ob->restrictflag &= ~OB_RESTRICT_RENDER;
/* lowpoly to highpoly transformation matrix */
@@ -961,7 +971,7 @@ cage_cleanup:
md->mode &= ~eModifierMode_Render;
}
- me_nores = bake_mesh_new_from_object(RE_GetEvalCtx(re), bmain, scene, ob_low);
+ me_nores = bake_mesh_new_from_object(eval_ctx, bmain, scene, ob_low);
RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low->obmat);
@@ -1122,7 +1132,7 @@ static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
bkr->ob = CTX_data_active_object(C);
bkr->main = CTX_data_main(C);
- bkr->depsgraph = CTX_data_depsgraph(C);
+ bkr->view_layer = CTX_data_view_layer(C);
bkr->scene = CTX_data_scene(C);
bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL;
@@ -1206,7 +1216,7 @@ static int bake_exec(bContext *C, wmOperator *op)
if (bkr.is_selected_to_active) {
result = bake(
- bkr.render, bkr.main, bkr.depsgraph, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports,
+ bkr.render, bkr.main, bkr.scene, bkr.view_layer, bkr.ob, &bkr.selected_objects, bkr.reports,
bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode,
bkr.is_clear, bkr.is_split_materials, bkr.is_automatic_name, true, bkr.is_cage,
bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
@@ -1219,7 +1229,7 @@ static int bake_exec(bContext *C, wmOperator *op)
for (link = bkr.selected_objects.first; link; link = link->next) {
Object *ob_iter = link->ptr.data;
result = bake(
- bkr.render, bkr.main, bkr.depsgraph, bkr.scene, ob_iter, NULL, bkr.reports,
+ bkr.render, bkr.main, bkr.scene, bkr.view_layer, ob_iter, NULL, bkr.reports,
bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode,
is_clear, bkr.is_split_materials, bkr.is_automatic_name, false, bkr.is_cage,
bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
@@ -1264,7 +1274,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa
if (bkr->is_selected_to_active) {
bkr->result = bake(
- bkr->render, bkr->main, bkr->depsgraph, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports,
+ bkr->render, bkr->main, bkr->scene, bkr->view_layer, bkr->ob, &bkr->selected_objects, bkr->reports,
bkr->pass_type, bkr->pass_filter, bkr->margin, bkr->save_mode,
bkr->is_clear, bkr->is_split_materials, bkr->is_automatic_name, true, bkr->is_cage,
bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
@@ -1277,7 +1287,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa
for (link = bkr->selected_objects.first; link; link = link->next) {
Object *ob_iter = link->ptr.data;
bkr->result = bake(
- bkr->render, bkr->main, bkr->depsgraph, bkr->scene, ob_iter, NULL, bkr->reports,
+ bkr->render, bkr->main, bkr->scene, bkr->view_layer, ob_iter, NULL, bkr->reports,
bkr->pass_type, bkr->pass_filter, bkr->margin, bkr->save_mode,
is_clear, bkr->is_split_materials, bkr->is_automatic_name, false, bkr->is_cage,
bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 05a5f652382..1a20a8db5b3 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -684,6 +684,8 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
static int stretchto_reset_exec(bContext *C, wmOperator *op)
{
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_STRETCHTO);
bStretchToConstraint *data = (con) ? (bStretchToConstraint *)con->data : NULL;
@@ -730,6 +732,8 @@ void CONSTRAINT_OT_stretchto_reset(wmOperatorType *ot)
static int limitdistance_reset_exec(bContext *C, wmOperator *op)
{
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_DISTLIMIT);
bDistLimitConstraint *data = (con) ? (bDistLimitConstraint *)con->data : NULL;
@@ -866,6 +870,8 @@ static void child_get_inverse_matrix(const bContext *C, Scene *scene, Object *ob
/* ChildOf Constraint - set inverse callback */
static int childof_set_inverse_exec(bContext *C, wmOperator *op)
{
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
@@ -917,6 +923,8 @@ void CONSTRAINT_OT_childof_set_inverse(wmOperatorType *ot)
static int childof_clear_inverse_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_active_context(C);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL;
@@ -964,6 +972,8 @@ void CONSTRAINT_OT_childof_clear_inverse(wmOperatorType *ot)
static int followpath_path_animate_exec(bContext *C, wmOperator *op)
{
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_FOLLOWPATH);
bFollowPathConstraint *data = (con) ? (bFollowPathConstraint *)con->data : NULL;
@@ -1088,6 +1098,8 @@ void CONSTRAINT_OT_followpath_path_animate(wmOperatorType *ot)
static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
{
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
@@ -1137,6 +1149,8 @@ void CONSTRAINT_OT_objectsolver_set_inverse(wmOperatorType *ot)
static int objectsolver_clear_inverse_exec(bContext *C, wmOperator *op)
{
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL;
@@ -1306,6 +1320,8 @@ void CONSTRAINT_OT_delete(wmOperatorType *ot)
static int constraint_move_down_exec(bContext *C, wmOperator *op)
{
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, 0);
@@ -1355,6 +1371,8 @@ void CONSTRAINT_OT_move_down(wmOperatorType *ot)
static int constraint_move_up_exec(bContext *C, wmOperator *op)
{
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, 0);
@@ -1575,6 +1593,8 @@ void OBJECT_OT_constraints_copy(wmOperatorType *ot)
/* get the Object and/or PoseChannel to use as target */
static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob, bPoseChannel **tar_pchan, bool add)
{
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
Object *obact = ED_object_active_context(C);
bPoseChannel *pchanact = BKE_pose_channel_active(obact);
bool only_curve = false, only_mesh = false, only_ob = false;
@@ -1653,7 +1673,7 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob
/* for armatures in pose mode, look inside the armature for the active bone
* so that we set up cross-armature constraints with less effort
*/
- if ((ob->type == OB_ARMATURE) && (ob->mode & OB_MODE_POSE) &&
+ if ((ob->type == OB_ARMATURE) && (eval_ctx.mode & OB_MODE_POSE) &&
(!only_curve && !only_mesh))
{
/* just use the active bone, and assume that it is visible + usable */
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 6222dbbf01b..b4fa27c3fd9 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -54,15 +54,17 @@
#include "DNA_property_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_vfont_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_lattice_types.h"
#include "DNA_workspace_types.h"
#include "IMB_imbuf_types.h"
#include "BKE_anim.h"
+#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_curve.h"
@@ -76,13 +78,16 @@
#include "BKE_mball.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
+#include "BKE_paint.h"
#include "BKE_pointcache.h"
#include "BKE_property.h"
#include "BKE_sca.h"
#include "BKE_softbody.h"
#include "BKE_modifier.h"
+#include "BKE_editlattice.h"
#include "BKE_editmesh.h"
#include "BKE_report.h"
+#include "BKE_object.h"
#include "BKE_workspace.h"
#include "DEG_depsgraph.h"
@@ -96,7 +101,7 @@
#include "ED_lattice.h"
#include "ED_object.h"
#include "ED_screen.h"
-#include "ED_util.h"
+#include "ED_undo.h"
#include "ED_image.h"
#include "RNA_access.h"
@@ -106,11 +111,16 @@
/* for menu/popup icons etc etc*/
#include "UI_interface.h"
+#include "UI_resources.h"
#include "WM_api.h"
#include "WM_types.h"
#include "object_intern.h" // own include
+/* prototypes */
+typedef struct MoveToCollectionData MoveToCollectionData;
+static void move_to_collection_menus_items(struct uiLayout *layout, struct MoveToCollectionData *menu);
+
/* ************* XXX **************** */
static void error(const char *UNUSED(arg)) {}
static void waitcursor(int UNUSED(val)) {}
@@ -172,6 +182,9 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f
if (obedit->type == OB_MESH) {
Mesh *me = obedit->data;
+ if (me->edit_btmesh == NULL) {
+ return false;
+ }
if (me->edit_btmesh->bm->totvert > MESH_MAX_VERTS) {
error("Too many vertices");
@@ -185,15 +198,21 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f
MEM_freeN(me->edit_btmesh);
me->edit_btmesh = NULL;
}
- if (obedit->restore_mode & OB_MODE_WEIGHT_PAINT) {
+ /* will be recalculated as needed. */
+ {
ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
ED_mesh_mirror_topo_table(NULL, NULL, 'e');
}
}
else if (obedit->type == OB_ARMATURE) {
+ const bArmature *arm = obedit->data;
+ if (arm->edbo == NULL) {
+ return false;
+ }
ED_armature_from_edit(obedit->data);
- if (freedata)
+ if (freedata) {
ED_armature_edit_free(obedit->data);
+ }
/* TODO(sergey): Pose channels might have been changed, so need
* to inform dependency graph about this. But is it really the
* best place to do this?
@@ -201,31 +220,50 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f
DEG_relations_tag_update(bmain);
}
else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ const Curve *cu = obedit->data;
+ if (cu->editnurb == NULL) {
+ return false;
+ }
ED_curve_editnurb_load(obedit);
- if (freedata) ED_curve_editnurb_free(obedit);
+ if (freedata) {
+ ED_curve_editnurb_free(obedit);
+ }
}
else if (obedit->type == OB_FONT) {
+ const Curve *cu = obedit->data;
+ if (cu->editfont == NULL) {
+ return false;
+ }
ED_curve_editfont_load(obedit);
- if (freedata) ED_curve_editfont_free(obedit);
+ if (freedata) {
+ ED_curve_editfont_free(obedit);
+ }
}
else if (obedit->type == OB_LATTICE) {
- ED_lattice_editlatt_load(obedit);
- if (freedata) ED_lattice_editlatt_free(obedit);
+ const Lattice *lt = obedit->data;
+ if (lt->editlatt == NULL) {
+ return false;
+ }
+ BKE_editlattice_load(obedit);
+ if (freedata) {
+ BKE_editlattice_free(obedit);
+ }
}
else if (obedit->type == OB_MBALL) {
+ const MetaBall *mb = obedit->data;
+ if (mb->editelems == NULL) {
+ return false;
+ }
ED_mball_editmball_load(obedit);
- if (freedata) ED_mball_editmball_free(obedit);
+ if (freedata) {
+ ED_mball_editmball_free(obedit);
+ }
}
else if (obedit->type == OB_GROOM) {
ED_groom_editgroom_load(obedit);
if (freedata) ED_groom_editgroom_free(obedit);
}
- /* Tag update so no access to freed data referenced from
- * derived cache will happen.
- */
- DEG_id_tag_update((ID *)obedit->data, 0);
-
return true;
}
@@ -235,18 +273,23 @@ bool ED_object_editmode_load(Object *obedit)
return ED_object_editmode_load_ex(G.main, obedit, false);
}
-void ED_object_editmode_exit(bContext *C, int flag)
+/**
+ * \param C: Can be NULL, only if #EM_DO_UNDO isn't set.
+ * \param flag:
+ * - Only in exceptional cases should #EM_DO_UNDO NOT be in the flag.
+ * - If #EM_FREEDATA isn't in the flag, use ED_object_editmode_load directly.
+ */
+void ED_object_editmode_exit_ex(bContext *C, Scene *scene, Object *obedit, int flag)
{
+ BLI_assert(C || !(flag & EM_DO_UNDO));
/* Note! only in exceptional cases should 'EM_DO_UNDO' NOT be in the flag */
/* Note! if 'EM_FREEDATA' isn't in the flag, use ED_object_editmode_load directly */
- Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *obedit = CTX_data_edit_object(C);
const bool freedata = (flag & EM_FREEDATA) != 0;
if (flag & EM_WAITCURSOR) waitcursor(1);
- if (ED_object_editmode_load_ex(CTX_data_main(C), obedit, freedata) == false) {
+ if (ED_object_editmode_load_ex(G.main, obedit, freedata) == false) {
/* in rare cases (background mode) its possible active object
* is flagged for editmode, without 'obedit' being set [#35489] */
if (UNLIKELY(view_layer->basact && (view_layer->basact->object->mode & OB_MODE_EDIT))) {
@@ -261,9 +304,6 @@ void ED_object_editmode_exit(bContext *C, int flag)
ListBase pidlist;
PTCacheID *pid;
- /* for example; displist make is different in editmode */
- scene->obedit = NULL; // XXX for context
-
/* flag object caches as outdated */
BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0);
for (pid = pidlist.first; pid; pid = pid->next) {
@@ -291,6 +331,12 @@ void ED_object_editmode_exit(bContext *C, int flag)
DEG_id_tag_update(&scene->id, 0);
}
+void ED_object_editmode_exit(bContext *C, int flag)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ ED_object_editmode_exit_ex(C, scene, obedit, flag);
+}
void ED_object_editmode_enter(bContext *C, int flag)
{
@@ -328,18 +374,16 @@ void ED_object_editmode_enter(bContext *C, int flag)
/* note, when switching scenes the object can have editmode data but
* not be scene->obedit: bug 22954, this avoids calling self eternally */
if ((ob->restore_mode & OB_MODE_EDIT) == 0)
- ED_object_toggle_modes(C, ob->mode);
+ ED_object_mode_toggle(C, ob->mode);
ob->mode = OB_MODE_EDIT;
if (ob->type == OB_MESH) {
BMEditMesh *em;
ok = 1;
- scene->obedit = ob; /* context sees this */
-
const bool use_key_index = mesh_needs_keyindex(ob->data);
- EDBM_mesh_make(scene->toolsettings, ob, use_key_index);
+ EDBM_mesh_make(ob, scene->toolsettings->selectmode, use_key_index);
em = BKE_editmesh_from_object(ob);
if (LIKELY(em)) {
@@ -366,7 +410,6 @@ void ED_object_editmode_enter(bContext *C, int flag)
return;
}
ok = 1;
- scene->obedit = ob;
ED_armature_to_edit(arm);
/* to ensure all goes in restposition and without striding */
DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* XXX: should this be OB_RECALC_DATA? */
@@ -374,35 +417,30 @@ void ED_object_editmode_enter(bContext *C, int flag)
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_ARMATURE, scene);
}
else if (ob->type == OB_FONT) {
- scene->obedit = ob; /* XXX for context */
ok = 1;
ED_curve_editfont_make(ob);
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_TEXT, scene);
}
else if (ob->type == OB_MBALL) {
- scene->obedit = ob; /* XXX for context */
ok = 1;
ED_mball_editmball_make(ob);
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_MBALL, scene);
}
else if (ob->type == OB_LATTICE) {
- scene->obedit = ob; /* XXX for context */
ok = 1;
- ED_lattice_editlatt_make(ob);
+ BKE_editlattice_make(ob);
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_LATTICE, scene);
}
else if (ob->type == OB_SURF || ob->type == OB_CURVE) {
ok = 1;
- scene->obedit = ob; /* XXX for context */
ED_curve_editnurb_make(ob);
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_CURVE, scene);
}
else if (ob->type == OB_GROOM) {
- scene->obedit = ob; /* XXX for context */
ok = 1;
ED_groom_editgroom_make(ob);
@@ -415,7 +453,6 @@ void ED_object_editmode_enter(bContext *C, int flag)
DEG_id_tag_update(&scene->id, 0);
}
else {
- scene->obedit = NULL; /* XXX for context */
ob->mode &= ~OB_MODE_EDIT;
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
}
@@ -440,7 +477,7 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op)
if (!is_mode_set)
ED_object_editmode_enter(C, EM_WAITCURSOR);
else
- ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR); /* had EM_DO_UNDO but op flag calls undo too [#24685] */
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR); /* had EM_DO_UNDO but op flag calls undo too [#24685] */
ED_space_image_uv_sculpt_update(CTX_wm_manager(C), scene);
@@ -456,8 +493,9 @@ static int editmode_toggle_poll(bContext *C)
return 0;
/* if hidden but in edit mode, we still display */
- if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT))
+ if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)) {
return 0;
+ }
return OB_TYPE_SUPPORT_EDITMODE(ob->type);
}
@@ -485,7 +523,7 @@ static int posemode_exec(bContext *C, wmOperator *op)
Base *base = CTX_data_active_base(C);
Object *ob = base->object;
const int mode_flag = OB_MODE_POSE;
- const bool is_mode_set = (ob->mode & mode_flag) != 0;
+ bool is_mode_set = (ob->mode & mode_flag) != 0;
if (!is_mode_set) {
if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
@@ -496,13 +534,15 @@ static int posemode_exec(bContext *C, wmOperator *op)
if (ob->type == OB_ARMATURE) {
if (ob == CTX_data_edit_object(C)) {
ED_object_editmode_exit(C, EM_FREEDATA | EM_DO_UNDO);
- ED_armature_enter_posemode(C, base);
+ is_mode_set = false;
+ }
+
+ if (is_mode_set) {
+ ED_object_posemode_exit(C, ob);
+ }
+ else {
+ ED_object_posemode_enter(C, ob);
}
- else if (is_mode_set)
- ED_armature_exit_posemode(C, base);
- else
- ED_armature_enter_posemode(C, base);
-
return OPERATOR_FINISHED;
}
@@ -683,7 +723,7 @@ static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short ev
if (!(ob = OBACT(view_layer))) return;
- if (scene->obedit) { // XXX get from context
+ if (BKE_object_is_in_editmode(ob)) {
/* obedit_copymenu(); */
return;
}
@@ -880,7 +920,7 @@ static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short ev
}
else if (event == 26) {
#if 0 // XXX old animation system
- copy_nlastrips(&base->object->nlastrips, &ob->nlastrips);
+ BKE_nlastrip_copy(s(&base->object->nlastrips, &ob->nlastrips);
#endif // XXX old animation system
}
else if (event == 27) { /* autosmooth */
@@ -922,7 +962,7 @@ static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short ev
DEG_relations_tag_update(bmain);
}
-static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, ViewLayer *view_layer)
+static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, ViewLayer *view_layer, Object *obedit)
{
Object *ob;
short event;
@@ -930,7 +970,7 @@ static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, ViewLaye
if (!(ob = OBACT(view_layer))) return;
- if (scene->obedit) { /* XXX get from context */
+ if (obedit) {
/* if (ob->type == OB_MESH) */
/* XXX mesh_copy_menu(); */
return;
@@ -1011,7 +1051,7 @@ static int forcefield_toggle_exec(bContext *C, wmOperator *UNUSED(op))
ob->pd->forcefield = PFIELD_FORCE;
else
ob->pd->forcefield = 0;
-
+
ED_object_check_force_modifiers(CTX_data_main(C), CTX_data_scene(C), ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
@@ -1346,7 +1386,7 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot)
/* ********************** */
-static void UNUSED_FUNCTION(image_aspect) (Scene *scene, ViewLayer *view_layer)
+static void UNUSED_FUNCTION(image_aspect) (Scene *scene, ViewLayer *view_layer, Object *obedit)
{
/* all selected objects with an image map: scale in image aspect */
Base *base;
@@ -1356,7 +1396,7 @@ static void UNUSED_FUNCTION(image_aspect) (Scene *scene, ViewLayer *view_layer)
float x, y, space;
int a, b, done;
- if (scene->obedit) return; // XXX get from context
+ if (obedit) return;
if (ID_IS_LINKED(scene)) return;
for (base = FIRSTBASE(view_layer); base; base = base->next) {
@@ -1458,97 +1498,6 @@ static const EnumPropertyItem *object_mode_set_itemsf(
return item;
}
-static const char *object_mode_op_string(int mode)
-{
- if (mode & OB_MODE_EDIT)
- return "OBJECT_OT_editmode_toggle";
- if (mode == OB_MODE_SCULPT)
- return "SCULPT_OT_sculptmode_toggle";
- if (mode == OB_MODE_VERTEX_PAINT)
- return "PAINT_OT_vertex_paint_toggle";
- if (mode == OB_MODE_WEIGHT_PAINT)
- return "PAINT_OT_weight_paint_toggle";
- if (mode == OB_MODE_TEXTURE_PAINT)
- return "PAINT_OT_texture_paint_toggle";
- if (mode == OB_MODE_PARTICLE_EDIT)
- return "PARTICLE_OT_particle_edit_toggle";
- if (mode == OB_MODE_POSE)
- return "OBJECT_OT_posemode_toggle";
- if (mode == OB_MODE_GPENCIL)
- return "GPENCIL_OT_editmode_toggle";
- return NULL;
-}
-
-/* checks the mode to be set is compatible with the object
- * should be made into a generic function
- */
-static bool object_mode_compat_test(Object *ob, eObjectMode mode)
-{
- if (ob) {
- if (mode == OB_MODE_OBJECT)
- return true;
- else if (mode == OB_MODE_GPENCIL)
- return true; /* XXX: assume this is the case for now... */
-
- switch (ob->type) {
- case OB_MESH:
- if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT |
- OB_MODE_TEXTURE_PAINT | OB_MODE_PARTICLE_EDIT))
- {
- return true;
- }
- break;
- case OB_CURVE:
- case OB_SURF:
- case OB_FONT:
- case OB_MBALL:
- case OB_GROOM:
- if (mode & (OB_MODE_EDIT))
- return true;
- break;
- case OB_LATTICE:
- if (mode & (OB_MODE_EDIT | OB_MODE_WEIGHT_PAINT))
- return true;
- break;
- case OB_ARMATURE:
- if (mode & (OB_MODE_EDIT | OB_MODE_POSE))
- return true;
- break;
- }
- }
-
- return false;
-}
-
-/**
- * Sets the mode to a compatible state (use before entering the mode).
- *
- * This is so each mode's exec function can call
- */
-bool ED_object_mode_compat_set(bContext *C, Object *ob, int mode, ReportList *reports)
-{
- bool ok;
- if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) {
- const char *opstring = object_mode_op_string(ob->mode);
-
- WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
-#ifdef USE_WORKSPACE_MODE
- BKE_workspace_object_mode_set(CTX_wm_workspace(C), CTX_data_scene(C), ob->mode);
-#endif
-
- ok = ELEM(ob->mode, mode, OB_MODE_OBJECT);
- if (!ok) {
- wmOperatorType *ot = WM_operatortype_find(opstring, false);
- BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name);
- }
- }
- else {
- ok = true;
- }
-
- return ok;
-}
-
static int object_mode_set_poll(bContext *C)
{
/* Since Grease Pencil editmode is also handled here,
@@ -1588,7 +1537,7 @@ static int object_mode_set_exec(bContext *C, wmOperator *op)
}
}
- if (!ob || !object_mode_compat_test(ob, mode))
+ if (!ob || !ED_object_mode_compat_test(ob, mode))
return OPERATOR_PASS_THROUGH;
if (ob->mode != mode) {
@@ -1599,20 +1548,20 @@ static int object_mode_set_exec(bContext *C, wmOperator *op)
/* Exit current mode if it's not the mode we're setting */
if (mode != OB_MODE_OBJECT && (ob->mode != mode || toggle)) {
/* Enter new mode */
- ED_object_toggle_modes(C, mode);
+ ED_object_mode_toggle(C, mode);
}
if (toggle) {
/* Special case for Object mode! */
if (mode == OB_MODE_OBJECT && restore_mode == OB_MODE_OBJECT && ob->restore_mode != OB_MODE_OBJECT) {
- ED_object_toggle_modes(C, ob->restore_mode);
+ ED_object_mode_toggle(C, ob->restore_mode);
}
else if (ob->mode == mode) {
/* For toggling, store old mode so we know what to go back to */
ob->restore_mode = restore_mode;
}
else if (ob->restore_mode != OB_MODE_OBJECT && ob->restore_mode != mode) {
- ED_object_toggle_modes(C, ob->restore_mode);
+ ED_object_mode_toggle(C, ob->restore_mode);
}
}
@@ -1644,28 +1593,6 @@ void OBJECT_OT_mode_set(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-
-void ED_object_toggle_modes(bContext *C, int mode)
-{
- if (mode != OB_MODE_OBJECT) {
- const char *opstring = object_mode_op_string(mode);
-
- if (opstring) {
-#ifdef USE_WORKSPACE_MODE
- WorkSpace *workspace = CTX_wm_workspace(C);
-#endif
- WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
-
-#ifdef USE_WORKSPACE_MODE
- Object *ob = CTX_data_active_object(C);
- if (ob) {
- BKE_workspace_object_mode_set(workspace, CTX_data_scene(C), ob->mode);
- }
-#endif
- }
- }
-}
-
/************************ Game Properties ***********************/
static int game_property_new_exec(bContext *C, wmOperator *op)
@@ -2053,8 +1980,6 @@ void OBJECT_OT_game_physics_copy(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* generic utility function */
-
bool ED_object_editmode_calc_active_center(Object *obedit, const bool select_only, float r_center[3])
{
switch (obedit->type) {
@@ -2116,3 +2041,278 @@ bool ED_object_editmode_calc_active_center(Object *obedit, const bool select_onl
return false;
}
+
+#define COLLECTION_INVALID_INDEX -1
+
+static int move_to_collection_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "collection_index");
+ const bool is_add = RNA_boolean_get(op->ptr, "is_add");
+ const bool is_new = RNA_boolean_get(op->ptr, "is_new");
+ SceneCollection *scene_collection;
+
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ BKE_report(op->reports, RPT_ERROR, "No collection selected");
+ return OPERATOR_CANCELLED;
+ }
+
+ int collection_index = RNA_property_int_get(op->ptr, prop);
+ scene_collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
+ if (scene_collection == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unexpected error, collection not found");
+ return OPERATOR_CANCELLED;
+ }
+
+ Object *single_object = NULL;
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
+ {
+ if (single_object != NULL) {
+ single_object = NULL;
+ break;
+ }
+ else {
+ single_object = ob;
+ }
+ }
+ CTX_DATA_END;
+
+ if (is_new) {
+ char new_collection_name[MAX_NAME];
+ RNA_string_get(op->ptr, "new_collection_name", new_collection_name);
+ scene_collection = BKE_collection_add(&scene->id, scene_collection, COLLECTION_TYPE_NONE, new_collection_name);
+ }
+
+ if ((single_object != NULL) &&
+ is_add &&
+ BLI_findptr(&scene_collection->objects, single_object, offsetof(LinkData, data)))
+ {
+ BKE_reportf(op->reports, RPT_ERROR, "%s already in %s", single_object->id.name + 2, scene_collection->name);
+ return OPERATOR_CANCELLED;
+ }
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
+ {
+ if (!is_add) {
+ BKE_collection_object_move(&scene->id, scene_collection, NULL, ob);
+ }
+ else {
+ BKE_collection_object_add(&scene->id, scene_collection, ob);
+ }
+ }
+ CTX_DATA_END;
+
+ BKE_reportf(op->reports,
+ RPT_INFO,
+ "%s %s to %s",
+ (single_object != NULL) ? single_object->id.name + 2 : "Objects",
+ is_add ? "added" : "moved",
+ scene_collection->name);
+
+ DEG_relations_tag_update(CTX_data_main(C));
+ DEG_id_tag_update(&scene->id, 0);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+typedef struct MoveToCollectionData {
+ struct MoveToCollectionData *next, *prev;
+ int index;
+ struct SceneCollection *collection;
+ struct ListBase submenus;
+ PointerRNA ptr;
+ struct wmOperatorType *ot;
+} MoveToCollectionData;
+
+static int move_to_collection_menus_create(wmOperator *op, MoveToCollectionData *menu)
+{
+ int index = menu->index;
+ for (SceneCollection *scene_collection = menu->collection->scene_collections.first;
+ scene_collection != NULL;
+ scene_collection = scene_collection->next)
+ {
+ MoveToCollectionData *submenu = MEM_callocN(sizeof(MoveToCollectionData),
+ "MoveToCollectionData submenu - expected memleak");
+ BLI_addtail(&menu->submenus, submenu);
+ submenu->collection = scene_collection;
+ submenu->index = ++index;
+ index = move_to_collection_menus_create(op, submenu);
+ submenu->ot = op->type;
+ }
+ return index;
+}
+
+static void move_to_collection_menus_free_recursive(MoveToCollectionData *menu)
+{
+ for (MoveToCollectionData *submenu = menu->submenus.first;
+ submenu != NULL;
+ submenu = submenu->next)
+ {
+ move_to_collection_menus_free_recursive(submenu);
+ }
+ BLI_freelistN(&menu->submenus);
+}
+
+static void move_to_collection_menus_free(MoveToCollectionData **menu)
+{
+ if (*menu == NULL) {
+ return;
+ }
+
+ move_to_collection_menus_free_recursive(*menu);
+ MEM_freeN(*menu);
+ *menu = NULL;
+}
+
+static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout, void *menu_v)
+{
+ MoveToCollectionData *menu = menu_v;
+
+ uiItemIntO(layout,
+ menu->collection->name,
+ ICON_NONE,
+ "OBJECT_OT_move_to_collection",
+ "collection_index",
+ menu->index);
+ uiItemS(layout);
+
+ for (MoveToCollectionData *submenu = menu->submenus.first;
+ submenu != NULL;
+ submenu = submenu->next)
+ {
+ move_to_collection_menus_items(layout, submenu);
+ }
+
+ uiItemS(layout);
+
+ WM_operator_properties_create_ptr(&menu->ptr, menu->ot);
+ RNA_int_set(&menu->ptr, "collection_index", menu->index);
+ RNA_boolean_set(&menu->ptr, "is_new", true);
+
+ uiItemFullO_ptr(layout,
+ menu->ot,
+ "New Collection",
+ ICON_ZOOMIN,
+ menu->ptr.data,
+ /* We use invoke here so we can read ctrl from event. */
+ WM_OP_INVOKE_DEFAULT,
+ 0,
+ NULL);
+}
+
+static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionData *menu)
+{
+ if (BLI_listbase_is_empty(&menu->submenus)) {
+ uiItemIntO(layout,
+ menu->collection->name,
+ ICON_NONE,
+ "OBJECT_OT_move_to_collection",
+ "collection_index",
+ menu->index);
+ }
+ else {
+ uiItemMenuF(layout,
+ menu->collection->name,
+ ICON_NONE,
+ move_to_collection_menu_create,
+ menu);
+ }
+}
+
+/* This is allocated statically because we need this available for the menus creation callback. */
+static MoveToCollectionData *master_collection_menu = NULL;
+
+static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ /* Reset the menus data for the current master collection, and free previously allocated data. */
+ move_to_collection_menus_free(&master_collection_menu);
+
+ PropertyRNA *prop;
+ prop = RNA_struct_find_property(op->ptr, "collection_index");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ int collection_index = RNA_property_int_get(op->ptr, prop);
+ RNA_boolean_set(op->ptr, "is_add", event->ctrl);
+
+ if (RNA_boolean_get(op->ptr, "is_new")) {
+ prop = RNA_struct_find_property(op->ptr, "new_collection_name");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ char name[MAX_NAME];
+ SceneCollection *scene_collection;
+
+ scene_collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
+ BKE_collection_new_name_get(&CTX_data_scene(C)->id, scene_collection, name);
+
+ RNA_property_string_set(op->ptr, prop, name);
+ return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 5 * UI_UNIT_Y);
+ }
+ }
+ return move_to_collection_exec(C, op);
+ }
+
+ SceneCollection *master_collection = BKE_collection_master(&CTX_data_scene(C)->id);
+
+ /* 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
+ * called to an operator that exit with OPERATOR_INTERFACE to launch a menu.
+ *
+ * So we are left with a memory that will necessarily leak. It's a small leak though.*/
+ if (master_collection_menu == NULL) {
+ master_collection_menu = MEM_callocN(sizeof(MoveToCollectionData),
+ "MoveToCollectionData menu - expected eventual memleak");
+ }
+
+ master_collection_menu->collection = master_collection;
+ master_collection_menu->ot = op->type;
+ move_to_collection_menus_create(op, master_collection_menu);
+
+ uiPopupMenu *pup;
+ uiLayout *layout;
+
+ /* Build the menus. */
+ pup = UI_popup_menu_begin(C, IFACE_("Move to Collection"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+
+ /* We use invoke here so we can read ctrl from event. */
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
+
+ move_to_collection_menu_create(C, layout, master_collection_menu);
+
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
+}
+
+void OBJECT_OT_move_to_collection(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Move to Collection";
+ ot->description = "Move to a collection only (Ctrl to add)";
+ ot->idname = "OBJECT_OT_move_to_collection";
+
+ /* api callbacks */
+ ot->exec = move_to_collection_exec;
+ ot->invoke = move_to_collection_invoke;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_int(ot->srna, "collection_index", COLLECTION_INVALID_INDEX, COLLECTION_INVALID_INDEX, INT_MAX,
+ "Collection Index", "Index of the collection to move to", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_boolean(ot->srna, "is_add", false, "Add", "Keep object in original collections as well");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_string(ot->srna, "new_collection_name", NULL, MAX_NAME, "Name",
+ "Name of the newly added collection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+#undef COLLECTION_INVALID_INDEX
diff --git a/source/blender/editors/object/object_facemap_ops.c b/source/blender/editors/object/object_facemap_ops.c
index 857446ac6b0..a076521b41d 100644
--- a/source/blender/editors/object/object_facemap_ops.c
+++ b/source/blender/editors/object/object_facemap_ops.c
@@ -35,6 +35,7 @@
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_workspace_types.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
@@ -173,7 +174,12 @@ static int face_map_supported_edit_mode_poll(bContext *C)
{
Object *ob = ED_object_context(C);
ID *data = (ob) ? ob->data : NULL;
- return (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib && ob->mode == OB_MODE_EDIT);
+ if (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib) {
+ if (ob->mode == OB_MODE_EDIT) {
+ return true;
+ }
+ }
+ return false;
}
static int face_map_add_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index 93546b1bd5d..3ff794772fa 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -319,7 +319,7 @@ static bool object_hook_index_array(Scene *scene, Object *obedit,
BMEditMesh *em;
EDBM_mesh_load(obedit);
- EDBM_mesh_make(scene->toolsettings, obedit, true);
+ EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
DEG_id_tag_update(obedit->data, 0);
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 5d6d643b9bd..944912ad6b6 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -95,6 +95,8 @@ void OBJECT_OT_game_property_move(struct wmOperatorType *ot);
void OBJECT_OT_logic_bricks_copy(struct wmOperatorType *ot);
void OBJECT_OT_game_physics_copy(struct wmOperatorType *ot);
+void OBJECT_OT_move_to_collection(struct wmOperatorType *ot);
+
/* object_select.c */
void OBJECT_OT_select_all(struct wmOperatorType *ot);
void OBJECT_OT_select_random(struct wmOperatorType *ot);
@@ -106,6 +108,7 @@ void OBJECT_OT_select_mirror(struct wmOperatorType *ot);
void OBJECT_OT_select_more(struct wmOperatorType *ot);
void OBJECT_OT_select_less(struct wmOperatorType *ot);
void OBJECT_OT_select_same_group(struct wmOperatorType *ot);
+void OBJECT_OT_select_same_collection(struct wmOperatorType *ot);
/* object_add.c */
void OBJECT_OT_add(struct wmOperatorType *ot);
@@ -139,16 +142,6 @@ void OBJECT_OT_hook_assign(struct wmOperatorType *ot);
void OBJECT_OT_hook_reset(struct wmOperatorType *ot);
void OBJECT_OT_hook_recenter(struct wmOperatorType *ot);
-/* object_lattice.c */
-void LATTICE_OT_select_all(struct wmOperatorType *ot);
-void LATTICE_OT_select_more(struct wmOperatorType *ot);
-void LATTICE_OT_select_less(struct wmOperatorType *ot);
-void LATTICE_OT_select_ungrouped(struct wmOperatorType *ot);
-void LATTICE_OT_select_random(struct wmOperatorType *ot);
-void LATTICE_OT_select_mirror(struct wmOperatorType *ot);
-void LATTICE_OT_make_regular(struct wmOperatorType *ot);
-void LATTICE_OT_flip(struct wmOperatorType *ot);
-
/* object_group.c */
void GROUP_OT_create(struct wmOperatorType *ot);
void GROUP_OT_objects_remove_all(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c
new file mode 100644
index 00000000000..9e6e6947320
--- /dev/null
+++ b/source/blender/editors/object/object_modes.c
@@ -0,0 +1,258 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Foundation, 2002-2008 full recode
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/object/object_modes.c
+ * \ingroup edobj
+ *
+ * General utils to handle mode switching,
+ * actual mode switching logic is per-object type.
+ */
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_workspace_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_report.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+
+#include "DEG_depsgraph.h"
+
+#include "ED_screen.h"
+
+#include "ED_object.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name High Level Mode Operations
+ *
+ * \{ */
+
+static const char *object_mode_op_string(eObjectMode mode)
+{
+ if (mode & OB_MODE_EDIT)
+ return "OBJECT_OT_editmode_toggle";
+ if (mode == OB_MODE_SCULPT)
+ return "SCULPT_OT_sculptmode_toggle";
+ if (mode == OB_MODE_VERTEX_PAINT)
+ return "PAINT_OT_vertex_paint_toggle";
+ if (mode == OB_MODE_WEIGHT_PAINT)
+ return "PAINT_OT_weight_paint_toggle";
+ if (mode == OB_MODE_TEXTURE_PAINT)
+ return "PAINT_OT_texture_paint_toggle";
+ if (mode == OB_MODE_PARTICLE_EDIT)
+ return "PARTICLE_OT_particle_edit_toggle";
+ if (mode == OB_MODE_POSE)
+ return "OBJECT_OT_posemode_toggle";
+ if (mode == OB_MODE_GPENCIL)
+ return "GPENCIL_OT_editmode_toggle";
+ return NULL;
+}
+
+/**
+ * Checks the mode to be set is compatible with the object
+ * should be made into a generic function
+ */
+bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode)
+{
+ if (ob) {
+ if (mode == OB_MODE_OBJECT)
+ return true;
+ else if (mode == OB_MODE_GPENCIL)
+ return true; /* XXX: assume this is the case for now... */
+
+ switch (ob->type) {
+ case OB_MESH:
+ if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT |
+ OB_MODE_TEXTURE_PAINT | OB_MODE_PARTICLE_EDIT))
+ {
+ return true;
+ }
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ case OB_FONT:
+ case OB_MBALL:
+ case OB_GROOM:
+ if (mode & (OB_MODE_EDIT))
+ return true;
+ break;
+ case OB_LATTICE:
+ if (mode & (OB_MODE_EDIT | OB_MODE_WEIGHT_PAINT))
+ return true;
+ break;
+ case OB_ARMATURE:
+ if (mode & (OB_MODE_EDIT | OB_MODE_POSE))
+ return true;
+ break;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Sets the mode to a compatible state (use before entering the mode).
+ *
+ * This is so each mode's exec function can call
+ */
+bool ED_object_mode_compat_set(bContext *C, Object *ob, eObjectMode mode, ReportList *reports)
+{
+ bool ok;
+ if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) {
+ const char *opstring = object_mode_op_string(ob->mode);
+
+ WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
+ ok = ELEM(ob->mode, mode, OB_MODE_OBJECT);
+ if (!ok) {
+ wmOperatorType *ot = WM_operatortype_find(opstring, false);
+ BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name);
+ }
+ }
+ else {
+ ok = true;
+ }
+
+ return ok;
+}
+
+void ED_object_mode_toggle(bContext *C, eObjectMode mode)
+{
+ if (mode != OB_MODE_OBJECT) {
+ const char *opstring = object_mode_op_string(mode);
+
+ if (opstring) {
+ WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
+ }
+ }
+}
+
+
+/* Wrapper for operator */
+void ED_object_mode_set(bContext *C, eObjectMode mode)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wm->op_undo_depth++;
+ /* needed so we don't do undo pushes. */
+ ED_object_mode_generic_enter(C, mode);
+ wm->op_undo_depth--;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Generic Mode Enter/Exit
+ *
+ * Supports exiting a mode without it being in the current context.
+ * This could be done for entering modes too if it's needed.
+ *
+ * \{ */
+
+bool ED_object_mode_generic_enter(
+ struct bContext *C, eObjectMode object_mode)
+{
+ Object *ob = CTX_data_active_object(C);
+ if (ob->mode == object_mode) {
+ return true;
+ }
+ wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_mode_set", false);
+ PointerRNA ptr;
+ WM_operator_properties_create_ptr(&ptr, ot);
+ RNA_enum_set(&ptr, "mode", object_mode);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
+ WM_operator_properties_free(&ptr);
+ return (ob->mode == object_mode);
+}
+
+/**
+ * Use for changing works-paces or changing active object.
+ * Caller can check #OB_MODE_ALL_MODE_DATA to test if this needs to be run.
+ */
+static bool ed_object_mode_generic_exit_ex(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene, struct Object *ob,
+ bool only_test)
+{
+ if (ob->mode & OB_MODE_EDIT) {
+ if (BKE_object_is_in_editmode(ob)) {
+ if (only_test) {
+ return true;
+ }
+ ED_object_editmode_exit_ex(NULL, scene, ob, EM_FREEDATA);
+ }
+ }
+ else if (ob->mode & OB_MODE_VERTEX_PAINT) {
+ if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_VERTEX_PAINT)) {
+ if (only_test) {
+ return true;
+ }
+ ED_object_vpaintmode_exit_ex(ob);
+ }
+ }
+ else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_WEIGHT_PAINT)) {
+ if (only_test) {
+ return true;
+ }
+ ED_object_wpaintmode_exit_ex(ob);
+ }
+ }
+ else if (ob->mode & OB_MODE_SCULPT) {
+ if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT)) {
+ if (only_test) {
+ return true;
+ }
+ ED_object_sculptmode_exit_ex(eval_ctx, scene, ob);
+ }
+ }
+ else {
+ if (only_test) {
+ return false;
+ }
+ BLI_assert((ob->mode & OB_MODE_ALL_MODE_DATA) == 0);
+ }
+
+ return false;
+}
+
+void ED_object_mode_generic_exit(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene, struct Object *ob)
+{
+ ed_object_mode_generic_exit_ex(eval_ctx, scene, ob, false);
+}
+
+bool ED_object_mode_generic_has_data(
+ const struct EvaluationContext *eval_ctx,
+ struct Object *ob)
+{
+ return ed_object_mode_generic_exit_ex(eval_ctx, NULL, ob, true);
+}
+
+/** \} */
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 2099ceaa10b..5458e4c173f 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -40,7 +40,7 @@
#include "DNA_key_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_scene_types.h"
#include "BLI_bitmap.h"
@@ -524,12 +524,9 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
return 1;
}
-static int modifier_apply_shape(ReportList *reports, const bContext *C, Scene *scene, Object *ob, ModifierData *md)
+static int modifier_apply_shape(ReportList *reports, const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ModifierData *md)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- EvaluationContext eval_ctx;
-
- CTX_data_eval_ctx(C, &eval_ctx);
md->scene = scene;
@@ -560,7 +557,7 @@ static int modifier_apply_shape(ReportList *reports, const bContext *C, Scene *s
return 0;
}
- dm = mesh_create_derived_for_modifier(&eval_ctx, scene, ob, md, 0);
+ dm = mesh_create_derived_for_modifier(eval_ctx, scene, ob, md, 0);
if (!dm) {
BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
return 0;
@@ -587,12 +584,9 @@ static int modifier_apply_shape(ReportList *reports, const bContext *C, Scene *s
return 1;
}
-static int modifier_apply_obdata(ReportList *reports, const bContext *C, Scene *scene, Object *ob, ModifierData *md)
+static int modifier_apply_obdata(ReportList *reports, const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ModifierData *md)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- EvaluationContext eval_ctx;
-
- CTX_data_eval_ctx(C, &eval_ctx);
md->scene = scene;
@@ -616,13 +610,13 @@ static int modifier_apply_obdata(ReportList *reports, const bContext *C, Scene *
multires_force_update(ob);
if (mmd && mmd->totlvl && mti->type == eModifierTypeType_OnlyDeform) {
- if (!multiresModifier_reshapeFromDeformMod(&eval_ctx, scene, mmd, ob, md)) {
+ if (!multiresModifier_reshapeFromDeformMod(eval_ctx, scene, mmd, ob, md)) {
BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
return 0;
}
}
else {
- dm = mesh_create_derived_for_modifier(&eval_ctx, scene, ob, md, 1);
+ dm = mesh_create_derived_for_modifier(eval_ctx, scene, ob, md, 1);
if (!dm) {
BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
return 0;
@@ -648,7 +642,7 @@ static int modifier_apply_obdata(ReportList *reports, const bContext *C, Scene *
BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices");
vertexCos = BKE_curve_nurbs_vertexCos_get(&cu->nurb, &numVerts);
- mti->deformVerts(md, &eval_ctx, ob, NULL, vertexCos, numVerts, 0);
+ mti->deformVerts(md, eval_ctx, ob, NULL, vertexCos, numVerts, 0);
BK_curve_nurbs_vertexCos_apply(&cu->nurb, vertexCos);
MEM_freeN(vertexCos);
@@ -670,18 +664,20 @@ static int modifier_apply_obdata(ReportList *reports, const bContext *C, Scene *
if (psys->part->type != PART_HAIR)
continue;
- psys_apply_hair_lattice(&eval_ctx, scene, ob, psys);
+ psys_apply_hair_lattice(eval_ctx, scene, ob, psys);
}
}
return 1;
}
-int ED_object_modifier_apply(ReportList *reports, const bContext *C, Scene *scene, Object *ob, ModifierData *md, int mode)
+int ED_object_modifier_apply(
+ ReportList *reports, const EvaluationContext *eval_ctx,
+ Scene *scene, Object *ob, ModifierData *md, int mode)
{
int prev_mode;
- if (scene->obedit) {
+ if (BKE_object_is_in_editmode(ob)) {
BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in edit mode");
return 0;
}
@@ -705,13 +701,13 @@ int ED_object_modifier_apply(ReportList *reports, const bContext *C, Scene *scen
md->mode |= eModifierMode_Realtime;
if (mode == MODIFIER_APPLY_SHAPE) {
- if (!modifier_apply_shape(reports, C, scene, ob, md)) {
+ if (!modifier_apply_shape(reports, eval_ctx, scene, ob, md)) {
md->mode = prev_mode;
return 0;
}
}
else {
- if (!modifier_apply_obdata(reports, C, scene, ob, md)) {
+ if (!modifier_apply_obdata(reports, eval_ctx, scene, ob, md)) {
md->mode = prev_mode;
return 0;
}
@@ -895,11 +891,13 @@ static int modifier_remove_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
/* if cloth/softbody was removed, particle mode could be cleared */
- if (mode_orig & OB_MODE_PARTICLE_EDIT)
- if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0)
- if (view_layer->basact && view_layer->basact->object == ob)
+ if (mode_orig & OB_MODE_PARTICLE_EDIT) {
+ if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) {
+ if (ob == OBACT(view_layer)) {
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
-
+ }
+ }
+ }
return OPERATOR_FINISHED;
}
@@ -1013,7 +1011,10 @@ static int modifier_apply_exec(bContext *C, wmOperator *op)
ModifierData *md = edit_modifier_property_get(op, ob, 0);
int apply_as = RNA_enum_get(op->ptr, "apply_as");
- if (!md || !ED_object_modifier_apply(op->reports, C, scene, ob, md, apply_as)) {
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ if (!md || !ED_object_modifier_apply(op->reports, &eval_ctx, scene, ob, md, apply_as)) {
return OPERATOR_CANCELLED;
}
@@ -1240,11 +1241,8 @@ static int multires_reshape_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_active_context(C), *secondob = NULL;
Scene *scene = CTX_data_scene(C);
- EvaluationContext eval_ctx;
MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
- CTX_data_eval_ctx(C, &eval_ctx);
-
if (!mmd)
return OPERATOR_CANCELLED;
@@ -1267,6 +1265,9 @@ static int multires_reshape_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (!multiresModifier_reshape(&eval_ctx, scene, mmd, ob, secondob)) {
BKE_report(op->reports, RPT_ERROR, "Objects do not have the same number of vertices");
return OPERATOR_CANCELLED;
@@ -1700,10 +1701,8 @@ static void skin_armature_bone_create(Object *skin_ob,
}
}
-static Object *modifier_skin_armature_create(const bContext *C, Scene *scene, ViewLayer *view_layer, Object *skin_ob)
+static Object *modifier_skin_armature_create(const EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Object *skin_ob)
{
- Main *bmain = CTX_data_main(C);
- EvaluationContext eval_ctx;
BLI_bitmap *edges_visited;
DerivedMesh *deform_dm;
MVert *mvert;
@@ -1715,9 +1714,7 @@ static Object *modifier_skin_armature_create(const bContext *C, Scene *scene, Vi
int *emap_mem;
int v;
- CTX_data_eval_ctx(C, &eval_ctx);
-
- deform_dm = mesh_get_derived_deform(&eval_ctx, scene, skin_ob, CD_MASK_BAREMESH);
+ deform_dm = mesh_get_derived_deform(eval_ctx, scene, skin_ob, CD_MASK_BAREMESH);
mvert = deform_dm->getVertArray(deform_dm);
/* add vertex weights to original mesh */
@@ -1727,7 +1724,7 @@ static Object *modifier_skin_armature_create(const bContext *C, Scene *scene, Vi
NULL,
me->totvert);
- arm_ob = BKE_object_add(bmain, scene, view_layer, OB_ARMATURE, NULL);
+ arm_ob = BKE_object_add(bmain, scene, eval_ctx->view_layer, OB_ARMATURE, NULL);
BKE_object_transform_copy(arm_ob, skin_ob);
arm = arm_ob->data;
arm->layer = 1;
@@ -1786,7 +1783,6 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = CTX_data_active_object(C), *arm_ob;
Mesh *me = ob->data;
ModifierData *skin_md;
@@ -1797,8 +1793,11 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* create new armature */
- arm_ob = modifier_skin_armature_create(C, scene, view_layer, ob);
+ arm_ob = modifier_skin_armature_create(&eval_ctx, bmain, scene, ob);
/* add a modifier to connect the new armature to the mesh */
arm_md = (ArmatureModifierData *)modifier_new(eModifierType_Armature);
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 733419d8474..a35a54001e8 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -47,6 +47,8 @@
#include "ED_screen.h"
#include "ED_object.h"
+#include "DEG_depsgraph.h"
+
#include "object_intern.h"
@@ -92,6 +94,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_select_random);
WM_operatortype_append(OBJECT_OT_select_all);
WM_operatortype_append(OBJECT_OT_select_same_group);
+ WM_operatortype_append(OBJECT_OT_select_same_collection);
WM_operatortype_append(OBJECT_OT_select_by_type);
WM_operatortype_append(OBJECT_OT_select_linked);
WM_operatortype_append(OBJECT_OT_select_grouped);
@@ -218,6 +221,8 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_logic_bricks_copy);
WM_operatortype_append(OBJECT_OT_game_physics_copy);
+ WM_operatortype_append(OBJECT_OT_move_to_collection);
+
WM_operatortype_append(OBJECT_OT_shape_key_add);
WM_operatortype_append(OBJECT_OT_shape_key_remove);
WM_operatortype_append(OBJECT_OT_shape_key_clear);
@@ -225,15 +230,6 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_shape_key_mirror);
WM_operatortype_append(OBJECT_OT_shape_key_move);
- WM_operatortype_append(LATTICE_OT_select_all);
- WM_operatortype_append(LATTICE_OT_select_more);
- WM_operatortype_append(LATTICE_OT_select_less);
- WM_operatortype_append(LATTICE_OT_select_ungrouped);
- WM_operatortype_append(LATTICE_OT_select_random);
- WM_operatortype_append(LATTICE_OT_select_mirror);
- WM_operatortype_append(LATTICE_OT_make_regular);
- WM_operatortype_append(LATTICE_OT_flip);
-
WM_operatortype_append(OBJECT_OT_group_add);
WM_operatortype_append(OBJECT_OT_group_link);
WM_operatortype_append(OBJECT_OT_group_remove);
@@ -432,29 +428,7 @@ void ED_keymap_object(wmKeyConfig *keyconf)
RNA_int_set(kmi->ptr, "level", i);
}
- /* ############################################################################ */
- /* ################################ LATTICE ################################### */
- /* ############################################################################ */
-
- keymap = WM_keymap_find(keyconf, "Lattice", 0, 0);
- keymap->poll = ED_operator_editlattice;
-
- kmi = WM_keymap_add_item(keymap, "LATTICE_OT_select_all", AKEY, KM_PRESS, 0, 0);
- RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE);
- kmi = WM_keymap_add_item(keymap, "LATTICE_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
- RNA_enum_set(kmi->ptr, "action", SEL_INVERT);
- WM_keymap_add_item(keymap, "LATTICE_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "LATTICE_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
-
- WM_keymap_add_item(keymap, "OBJECT_OT_vertex_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
-
- WM_keymap_add_item(keymap, "LATTICE_OT_flip", FKEY, KM_PRESS, KM_CTRL, 0);
-
- /* menus */
- WM_keymap_add_menu(keymap, "VIEW3D_MT_hook", HKEY, KM_PRESS, KM_CTRL, 0);
-
- ED_keymap_proportional_cycle(keyconf, keymap);
- ED_keymap_proportional_editmode(keyconf, keymap, false);
+ WM_keymap_add_item(keymap, "OBJECT_OT_move_to_collection", MKEY, KM_PRESS, 0, 0);
}
void ED_keymap_proportional_cycle(struct wmKeyConfig *UNUSED(keyconf), struct wmKeyMap *keymap)
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 13cc53c04a7..fee39c8f0fb 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -151,7 +151,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
BMEditMesh *em;
EDBM_mesh_load(obedit);
- EDBM_mesh_make(scene->toolsettings, obedit, true);
+ EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
DEG_id_tag_update(obedit->data, 0);
@@ -401,13 +401,13 @@ static const EnumPropertyItem *proxy_group_object_itemf(bContext *C, PointerRNA
return DummyRNA_DEFAULT_items;
/* find the object to affect */
- FOREACH_GROUP_OBJECT(ob->dup_group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(ob->dup_group, object)
{
item_tmp.identifier = item_tmp.name = object->id.name + 2;
item_tmp.value = i++;
RNA_enum_item_add(&item, &totitem, &item_tmp);
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
RNA_enum_item_end(&item, &totitem);
*r_free = true;
@@ -1629,33 +1629,30 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob, const bool copy_groups)
{
- if (!ID_IS_LINKED(ob) && ob->id.us > 1) {
- /* base gets copy of object */
- Object *obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
+ /* base gets copy of object */
+ Object *obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
- if (copy_groups) {
- if (ob->flag & OB_FROMGROUP) {
- obn->flag |= OB_FROMGROUP;
- }
- }
- else {
- /* copy already clears */
+ if (copy_groups) {
+ if (ob->flag & OB_FROMGROUP) {
+ obn->flag |= OB_FROMGROUP;
}
- /* remap gpencil parenting */
+ }
+ else {
+ /* copy already clears */
+ }
+ /* remap gpencil parenting */
- if (scene->gpd) {
- bGPdata *gpd = scene->gpd;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpl->parent == ob) {
- gpl->parent = obn;
- }
+ if (scene->gpd) {
+ bGPdata *gpd = scene->gpd;
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl->parent == ob) {
+ gpl->parent = obn;
}
}
-
- id_us_min(&ob->id);
- return obn;
}
- return NULL;
+
+ id_us_min(&ob->id);
+ return obn;
}
static void libblock_relink_scene_collection(SceneCollection *sc)
@@ -1675,7 +1672,9 @@ static void single_object_users_scene_collection(Main *bmain, Scene *scene, Scen
Object *ob = link->data;
/* an object may be in more than one collection */
if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) {
- link->data = single_object_users_object(bmain, scene, link->data, copy_groups);
+ if (!ID_IS_LINKED(ob) && ob->id.us > 1) {
+ link->data = single_object_users_object(bmain, scene, link->data, copy_groups);
+ }
}
}
@@ -1707,19 +1706,19 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
if (copy_groups && group->view_layer->object_bases.first) {
bool all_duplicated = true;
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
if (object->id.newid == NULL) {
all_duplicated = false;
break;
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
if (all_duplicated) {
groupn = ID_NEW_SET(group, BKE_group_copy(bmain, group));
- FOREACH_GROUP_BASE(groupn, base)
+ FOREACH_GROUP_BASE_BEGIN(groupn, base)
{
base->object = (Object *)base->object->id.newid;
}
@@ -1744,11 +1743,11 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
* button can be functional.*/
void ED_object_single_user(Main *bmain, Scene *scene, Object *ob)
{
- FOREACH_SCENE_OBJECT(scene, ob_iter)
+ FOREACH_SCENE_OBJECT_BEGIN(scene, ob_iter)
{
ob_iter->flag &= ~OB_DONE;
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
/* tag only the one object */
ob->flag |= OB_DONE;
@@ -1788,7 +1787,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer
ID *id;
int a;
- FOREACH_OBJECT_FLAG(scene, view_layer, flag, ob)
+ FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, flag, ob)
{
if (!ID_IS_LINKED(ob)) {
id = ob->data;
@@ -1849,7 +1848,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer
printf("ERROR %s: can't copy %s\n", __func__, id->name);
BLI_assert(!"This should never happen.");
- /* We need to end the FOREACH_OBJECT_FLAG iterator to prevent memory leak. */
+ /* We need to end the FOREACH_OBJECT_FLAG_BEGIN iterator to prevent memory leak. */
BKE_scene_objects_iterator_end(&iter_macro);
return;
}
@@ -1865,7 +1864,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer
}
}
}
- FOREACH_OBJECT_FLAG_END
+ FOREACH_OBJECT_FLAG_END;
me = bmain->mesh.first;
while (me) {
@@ -1876,12 +1875,14 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer
static void single_object_action_users(Scene *scene, ViewLayer *view_layer, const int flag)
{
- FOREACH_OBJECT_FLAG(scene, view_layer, flag, ob)
+ FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, flag, ob)
+ {
if (!ID_IS_LINKED(ob)) {
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
BKE_animdata_copy_id_action(&ob->id, false);
}
- FOREACH_OBJECT_FLAG_END
+ }
+ FOREACH_OBJECT_FLAG_END;
}
static void single_mat_users(Main *bmain, Scene *scene, ViewLayer *view_layer, const int flag, const bool do_textures)
@@ -1890,7 +1891,8 @@ static void single_mat_users(Main *bmain, Scene *scene, ViewLayer *view_layer, c
Tex *tex;
int a, b;
- FOREACH_OBJECT_FLAG(scene, view_layer, flag, ob)
+ FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, flag, ob)
+ {
if (!ID_IS_LINKED(ob)) {
for (a = 1; a <= ob->totcol; a++) {
ma = give_current_material(ob, a);
@@ -1920,7 +1922,8 @@ static void single_mat_users(Main *bmain, Scene *scene, ViewLayer *view_layer, c
}
}
}
- FOREACH_OBJECT_FLAG_END
+ }
+ FOREACH_OBJECT_FLAG_END;
}
static void do_single_tex_user(Main *bmain, Tex **from)
@@ -2045,13 +2048,13 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo
{
IDP_RelinkProperty(scene->id.properties);
- FOREACH_SCENE_OBJECT(scene, ob)
+ FOREACH_SCENE_OBJECT_BEGIN(scene, ob)
{
if (!ID_IS_LINKED(ob)) {
IDP_RelinkProperty(ob->id.properties);
}
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
if (scene->nodetree) {
IDP_RelinkProperty(scene->nodetree->id.properties);
@@ -2415,7 +2418,6 @@ static int make_override_static_exec(bContext *C, wmOperator *op)
bool success = false;
if (!ID_IS_LINKED(obact) && obact->dup_group != NULL && ID_IS_LINKED(obact->dup_group)) {
-#if 0 /* Not working yet! */
Base *base = BLI_findlink(&obact->dup_group->view_layer->object_bases, RNA_enum_get(op->ptr, "object"));
Object *obgroup = obact;
obact = base->object;
@@ -2426,9 +2428,9 @@ static int make_override_static_exec(bContext *C, wmOperator *op)
/* Then, we tag our 'main' object and its detected dependencies to be also overridden. */
obact->id.tag |= LIB_TAG_DOIT;
- FOREACH_GROUP_OBJECT(obgroup->dup_group, ob)
+ FOREACH_GROUP_OBJECT_BEGIN(obgroup->dup_group, ob)
{
- make_override_tag_object(obact, ob);
+ make_override_static_tag_object(obact, ob);
}
FOREACH_GROUP_OBJECT_END;
@@ -2439,7 +2441,7 @@ static int make_override_static_exec(bContext *C, wmOperator *op)
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *new_obact = (Object *)obact->id.newid;
if (new_obact != NULL && (base = BKE_view_layer_base_find(view_layer, new_obact)) == NULL) {
- BKE_collection_object_add_from(scene, obact, new_obact);
+ BKE_collection_object_add_from(scene, obgroup, new_obact);
base = BKE_view_layer_base_find(view_layer, new_obact);
BKE_view_layer_base_select(view_layer, base);
}
@@ -2457,9 +2459,6 @@ static int make_override_static_exec(bContext *C, wmOperator *op)
/* Cleanup. */
BKE_main_id_clear_newpoins(bmain);
BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, false);
-#else
- UNUSED_VARS(op);
-#endif
}
/* Else, poll func ensures us that ID_IS_LINKED(obact) is true. */
else if (obact->type == OB_ARMATURE) {
@@ -2516,8 +2515,8 @@ void OBJECT_OT_make_override_static(wmOperatorType *ot)
/* properties */
PropertyRNA *prop;
- prop = RNA_def_enum(ot->srna, "object", DummyRNA_DEFAULT_items, 0, "Proxy Object",
- "Name of lib-linked/grouped object to make a proxy for");
+ prop = RNA_def_enum(ot->srna, "object", DummyRNA_DEFAULT_items, 0, "Override Object",
+ "Name of lib-linked/group object to make an override from");
RNA_def_enum_funcs(prop, proxy_group_object_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index b20fe9a004c..cd1300dd52e 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -56,7 +56,9 @@
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_material.h"
+#include "BKE_object.h"
#include "BKE_particle.h"
+#include "BKE_paint.h"
#include "BKE_property.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -64,6 +66,8 @@
#include "BKE_library.h"
#include "BKE_deform.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -122,9 +126,6 @@ void ED_object_base_activate(bContext *C, Base *base)
view_layer->basact = base;
if (base) {
-#ifdef USE_WORKSPACE_MODE
- BKE_workspace_object_mode_set(CTX_wm_workspace(C), CTX_data_scene(C), base->object->mode);
-#endif
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, view_layer);
}
else {
@@ -498,7 +499,7 @@ enum {
OBJECT_GRPSEL_PARENT = 2,
OBJECT_GRPSEL_SIBLINGS = 3,
OBJECT_GRPSEL_TYPE = 4,
- /*OBJECT_GRPSEL_LAYER = 5,*/
+ OBJECT_GRPSEL_COLLECTION = 5,
OBJECT_GRPSEL_GROUP = 6,
OBJECT_GRPSEL_HOOK = 7,
OBJECT_GRPSEL_PASS = 8,
@@ -514,6 +515,7 @@ static const EnumPropertyItem prop_select_grouped_types[] = {
{OBJECT_GRPSEL_PARENT, "PARENT", 0, "Parent", ""},
{OBJECT_GRPSEL_SIBLINGS, "SIBLINGS", 0, "Siblings", "Shared Parent"},
{OBJECT_GRPSEL_TYPE, "TYPE", 0, "Type", "Shared object type"},
+ {OBJECT_GRPSEL_COLLECTION, "COLLECTION", 0, "Collection", "Shared collection"},
{OBJECT_GRPSEL_GROUP, "GROUP", 0, "Group", "Shared group"},
{OBJECT_GRPSEL_HOOK, "HOOK", 0, "Hook", ""},
{OBJECT_GRPSEL_PASS, "PASS", 0, "Pass", "Render pass Index"},
@@ -687,6 +689,60 @@ static bool select_grouped_type(bContext *C, Object *ob)
return changed;
}
+#define COLLECTION_MENU_MAX 24
+static bool select_grouped_collection(bContext *C, Object *ob) /* Select objects in the same collection as the active */
+{
+ typedef struct EnumeratedCollection {
+ struct SceneCollection *collection;
+ int index;
+ } EnumeratedCollection;
+
+ bool changed = false;
+ SceneCollection *collection;
+ EnumeratedCollection ob_collections[COLLECTION_MENU_MAX];
+ int collection_count = 0, i;
+ uiPopupMenu *pup;
+ uiLayout *layout;
+
+ i = 0;
+ FOREACH_SCENE_COLLECTION_BEGIN(CTX_data_scene(C), scene_collection)
+ {
+ if (BKE_collection_object_exists(scene_collection, ob)) {
+ ob_collections[collection_count].index = i;
+ ob_collections[collection_count].collection = scene_collection;
+ if (++collection_count >= COLLECTION_MENU_MAX) {
+ break;
+ }
+ }
+ i++;
+ }
+ FOREACH_SCENE_COLLECTION_END;
+
+ if (!collection_count) {
+ return 0;
+ }
+ else if (collection_count == 1) {
+ collection = ob_collections[0].collection;
+ return BKE_collection_objects_select(CTX_data_view_layer(C), collection);
+ }
+
+ /* build the menu. */
+ pup = UI_popup_menu_begin(C, IFACE_("Select Collection"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+
+ for (i = 0; i < collection_count; i++) {
+ uiItemIntO(layout,
+ ob_collections[i].collection->name,
+ ICON_NONE,
+ "OBJECT_OT_select_same_collection",
+ "collection_index",
+ ob_collections[i].index);
+ }
+
+ UI_popup_menu_end(C, pup);
+ return changed; /* The operator already handle this! */
+}
+
static bool select_grouped_index_object(bContext *C, Object *ob)
{
bool changed = false;
@@ -836,6 +892,9 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
case OBJECT_GRPSEL_TYPE:
changed |= select_grouped_type(C, ob);
break;
+ case OBJECT_GRPSEL_COLLECTION:
+ changed |= select_grouped_collection(C, ob);
+ break;
case OBJECT_GRPSEL_GROUP:
changed |= select_grouped_group(C, ob);
break;
@@ -1009,6 +1068,49 @@ void OBJECT_OT_select_same_group(wmOperatorType *ot)
RNA_def_string(ot->srna, "group", NULL, MAX_ID_NAME, "Group", "Name of the group to select");
}
+/**************************** Select In The Same Collection ****************************/
+
+static int object_select_same_collection_exec(bContext *C, wmOperator *op)
+{
+ SceneCollection *collection;
+
+ /* passthrough if no objects are visible */
+ if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH;
+
+ int collection_index = RNA_int_get(op->ptr, "collection_index");
+ collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
+
+ if (!collection) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ if (BKE_collection_objects_select(CTX_data_view_layer(C), collection)) {
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_select_same_collection(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Same Collection";
+ ot->description = "Select object in the same collection";
+ ot->idname = "OBJECT_OT_select_same_collection";
+
+ /* api callbacks */
+ ot->exec = object_select_same_collection_exec;
+ ot->poll = objects_selectable_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_int(ot->srna, "collection_index", -1, -1, INT_MAX,
+ "Collection Index", "Index of the collection to select", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
/**************************** Select Mirror ****************************/
static int object_select_mirror_exec(bContext *C, wmOperator *op)
{
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 100b9018d00..bb23f871a25 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -982,7 +982,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
/* Function to recenter armatures in editarmature.c
* Bone + object locations are handled there.
*/
- ED_armature_origin_set(scene, ob, cursor, centermode, around);
+ ED_armature_origin_set(ob, cursor, centermode, around);
tot_change++;
arm->id.tag |= LIB_TAG_DOIT;
@@ -1285,7 +1285,7 @@ static void object_transform_axis_target_cancel(bContext *C, wmOperator *op)
static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewContext vc;
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
if (!object_is_target_compat(vc.obact)) {
/* Falls back to texture space transform. */
@@ -1342,9 +1342,9 @@ static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, cons
CTX_DATA_END;
xfd->object_data = object_data;
- xfd->object_data_len = BLI_array_count(object_data);
+ xfd->object_data_len = BLI_array_len(object_data);
- if (xfd->object_data_len != BLI_array_count(object_data)) {
+ if (xfd->object_data_len != BLI_array_len(object_data)) {
xfd->object_data = MEM_reallocN(xfd->object_data, xfd->object_data_len * sizeof(*xfd->object_data));
}
}
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index bf2da284591..7026e8671ad 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -43,6 +43,7 @@
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_alloca.h"
#include "BLI_array.h"
@@ -255,9 +256,10 @@ bool ED_vgroup_parray_alloc(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, co
*
* \note \a dvert_array has mirrored weights filled in, incase cleanup operations are needed on both.
*/
-void ED_vgroup_parray_mirror_sync(Object *ob,
- MDeformVert **dvert_array, const int dvert_tot,
- const bool *vgroup_validmap, const int vgroup_tot)
+void ED_vgroup_parray_mirror_sync(
+ Object *ob,
+ MDeformVert **dvert_array, const int dvert_tot,
+ const bool *vgroup_validmap, const int vgroup_tot)
{
BMEditMesh *em = BKE_editmesh_from_object(ob);
MDeformVert **dvert_array_all = NULL;
@@ -300,8 +302,9 @@ void ED_vgroup_parray_mirror_sync(Object *ob,
*
* similar to #ED_vgroup_parray_mirror_sync but only fill in mirror points.
*/
-void ED_vgroup_parray_mirror_assign(Object *ob,
- MDeformVert **dvert_array, const int dvert_tot)
+void ED_vgroup_parray_mirror_assign(
+ Object *ob,
+ MDeformVert **dvert_array, const int dvert_tot)
{
BMEditMesh *em = BKE_editmesh_from_object(ob);
MDeformVert **dvert_array_all = NULL;
@@ -332,9 +335,10 @@ void ED_vgroup_parray_mirror_assign(Object *ob,
MEM_freeN(dvert_array_all);
}
-void ED_vgroup_parray_remove_zero(MDeformVert **dvert_array, const int dvert_tot,
- const bool *vgroup_validmap, const int vgroup_tot,
- const float epsilon, const bool keep_single)
+void ED_vgroup_parray_remove_zero(
+ MDeformVert **dvert_array, const int dvert_tot,
+ const bool *vgroup_validmap, const int vgroup_tot,
+ const float epsilon, const bool keep_single)
{
MDeformVert *dv;
int i;
@@ -484,9 +488,10 @@ void ED_vgroup_parray_from_weight_array(
/* TODO, cache flip data to speedup calls within a loop. */
-static void mesh_defvert_mirror_update_internal(Object *ob,
- MDeformVert *dvert_dst, MDeformVert *dvert_src,
- const int def_nr)
+static void mesh_defvert_mirror_update_internal(
+ Object *ob,
+ MDeformVert *dvert_dst, MDeformVert *dvert_src,
+ const int def_nr)
{
if (def_nr == -1) {
/* all vgroups, add groups where neded */
@@ -504,8 +509,9 @@ static void mesh_defvert_mirror_update_internal(Object *ob,
}
}
-static void ED_mesh_defvert_mirror_update_em(Object *ob, BMVert *eve, int def_nr, int vidx,
- const int cd_dvert_offset)
+static void ED_mesh_defvert_mirror_update_em(
+ Object *ob, BMVert *eve, int def_nr, int vidx,
+ const int cd_dvert_offset)
{
Mesh *me = ob->data;
BMEditMesh *em = me->edit_btmesh;
@@ -713,26 +719,30 @@ const EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(
return item;
}
-static const EnumPropertyItem *rna_vertex_group_with_single_itemf(bContext *C, PointerRNA *ptr,
- PropertyRNA *prop, bool *r_free)
+static const EnumPropertyItem *rna_vertex_group_with_single_itemf(
+ bContext *C, PointerRNA *ptr,
+ PropertyRNA *prop, bool *r_free)
{
return ED_object_vgroup_selection_itemf_helper(C, ptr, prop, r_free, WT_VGROUP_MASK_ALL);
}
-static const EnumPropertyItem *rna_vertex_group_select_itemf(bContext *C, PointerRNA *ptr,
- PropertyRNA *prop, bool *r_free)
+static const EnumPropertyItem *rna_vertex_group_select_itemf(
+ bContext *C, PointerRNA *ptr,
+ PropertyRNA *prop, bool *r_free)
{
- return ED_object_vgroup_selection_itemf_helper(C, ptr, prop, r_free, WT_VGROUP_MASK_ALL & ~(1 << WT_VGROUP_ACTIVE));
+ return ED_object_vgroup_selection_itemf_helper(
+ C, ptr, prop, r_free, WT_VGROUP_MASK_ALL & ~(1 << WT_VGROUP_ACTIVE));
}
static void vgroup_operator_subset_select_props(wmOperatorType *ot, bool use_active)
{
PropertyRNA *prop;
- prop = RNA_def_enum(ot->srna,
- "group_select_mode", DummyRNA_NULL_items,
- use_active ? WT_VGROUP_ACTIVE : WT_VGROUP_ALL, "Subset",
- "Define which subset of Groups shall be used");
+ prop = RNA_def_enum(
+ ot->srna,
+ "group_select_mode", DummyRNA_NULL_items,
+ use_active ? WT_VGROUP_ACTIVE : WT_VGROUP_ALL, "Subset",
+ "Define which subset of Groups shall be used");
if (use_active) {
RNA_def_enum_funcs(prop, rna_vertex_group_with_single_itemf);
@@ -749,9 +759,10 @@ static void vgroup_operator_subset_select_props(wmOperatorType *ot, bool use_act
/* for Mesh in Object mode */
/* allows editmode for Lattice */
-static void ED_vgroup_nr_vert_add(Object *ob,
- const int def_nr, const int vertnum,
- const float weight, const int assignmode)
+static void ED_vgroup_nr_vert_add(
+ Object *ob,
+ const int def_nr, const int vertnum,
+ const float weight, const int assignmode)
{
/* add the vert to the deform group with the
* specified number
@@ -1179,7 +1190,7 @@ static int *getSurroundingVerts(Mesh *me, int vert, int *count)
}
/* Append a and b verts to array, if not yet present. */
- k = BLI_array_count(verts);
+ k = BLI_array_len(verts);
/* XXX Maybe a == b is enough? */
while (k-- && !(a == b && a == -1)) {
if (verts[k] == a)
@@ -1201,7 +1212,7 @@ static int *getSurroundingVerts(Mesh *me, int vert, int *count)
}
/* Do not free the array! */
- *count = BLI_array_count(verts);
+ *count = BLI_array_len(verts);
return verts;
}
@@ -1222,9 +1233,10 @@ static void getSingleCoordinate(MVert *points, int count, float coord[3])
* compute the amount of vertical distance relative to the plane and store it in dists,
* then get the horizontal and vertical change and store them in changes
*/
-static void getVerticalAndHorizontalChange(const float norm[3], float d, const float coord[3],
- const float start[3], float distToStart,
- float *end, float (*changes)[2], float *dists, int index)
+static void getVerticalAndHorizontalChange(
+ const float norm[3], float d, const float coord[3],
+ const float start[3], float distToStart,
+ float *end, float (*changes)[2], float *dists, int index)
{
/* A = Q - ((Q - P).N)N
* D = (a * x0 + b * y0 +c * z0 + d) */
@@ -1275,8 +1287,9 @@ static DerivedMesh *dm_deform_recalc(EvaluationContext *eval_ctx, Scene *scene,
* norm and d are the plane's properties for the equation: ax + by + cz + d = 0
* coord is a point on the plane
*/
-static void moveCloserToDistanceFromPlane(EvaluationContext *eval_ctx, Scene *scene, Object *ob, Mesh *me, int index, float norm[3],
- float coord[3], float d, float distToBe, float strength, float cp)
+static void moveCloserToDistanceFromPlane(
+ EvaluationContext *eval_ctx, Scene *scene, Object *ob, Mesh *me, int index, float norm[3],
+ float coord[3], float d, float distToBe, float strength, float cp)
{
DerivedMesh *dm;
MDeformWeight *dw;
@@ -1499,9 +1512,10 @@ static void vgroup_fix(const bContext *C, Scene *scene, Object *ob, float distTo
}
}
-static void vgroup_levels_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot,
- const int UNUSED(subset_count),
- const float offset, const float gain)
+static void vgroup_levels_subset(
+ Object *ob, const bool *vgroup_validmap, const int vgroup_tot,
+ const int UNUSED(subset_count),
+ const float offset, const float gain)
{
MDeformWeight *dw;
MDeformVert *dv, **dvert_array = NULL;
@@ -1536,8 +1550,9 @@ static void vgroup_levels_subset(Object *ob, const bool *vgroup_validmap, const
}
if (use_mirror && use_vert_sel) {
- ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot,
- vgroup_validmap, vgroup_tot);
+ ED_vgroup_parray_mirror_sync(
+ ob, dvert_array, dvert_tot,
+ vgroup_validmap, vgroup_tot);
}
MEM_freeN(dvert_array);
@@ -1594,12 +1609,14 @@ static bool vgroup_normalize_all(
/* in case its not selected */
if ((dv = dvert_array[i])) {
if (lock_flags) {
- defvert_normalize_lock_map(dv, vgroup_validmap, vgroup_tot,
- lock_flags, defbase_tot);
+ defvert_normalize_lock_map(
+ dv, vgroup_validmap, vgroup_tot,
+ lock_flags, defbase_tot);
}
else if (lock_active) {
- defvert_normalize_lock_single(dv, vgroup_validmap, vgroup_tot,
- def_nr);
+ defvert_normalize_lock_single(
+ dv, vgroup_validmap, vgroup_tot,
+ def_nr);
}
else {
defvert_normalize_subset(dv, vgroup_validmap, vgroup_tot);
@@ -1666,9 +1683,10 @@ static void vgroup_lock_all(Object *ob, int action)
}
}
-static void vgroup_invert_subset(Object *ob,
- const bool *vgroup_validmap, const int vgroup_tot,
- const int UNUSED(subset_count), const bool auto_assign, const bool auto_remove)
+static void vgroup_invert_subset(
+ Object *ob,
+ const bool *vgroup_validmap, const int vgroup_tot,
+ const int UNUSED(subset_count), const bool auto_assign, const bool auto_remove)
{
MDeformWeight *dw;
MDeformVert *dv, **dvert_array = NULL;
@@ -1707,14 +1725,16 @@ static void vgroup_invert_subset(Object *ob,
}
if (use_mirror && use_vert_sel) {
- ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot,
- vgroup_validmap, vgroup_tot);
+ ED_vgroup_parray_mirror_sync(
+ ob, dvert_array, dvert_tot,
+ vgroup_validmap, vgroup_tot);
}
if (auto_remove) {
- ED_vgroup_parray_remove_zero(dvert_array, dvert_tot,
- vgroup_validmap, vgroup_tot,
- 0.0f, false);
+ ED_vgroup_parray_remove_zero(
+ dvert_array, dvert_tot,
+ vgroup_validmap, vgroup_tot,
+ 0.0f, false);
}
MEM_freeN(dvert_array);
@@ -1934,8 +1954,9 @@ static void vgroup_smooth_subset(
/* not so efficient to get 'dvert_array' again just so unselected verts are NULL'd */
if (use_mirror) {
ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, true);
- ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot,
- vgroup_validmap, vgroup_tot);
+ ED_vgroup_parray_mirror_sync(
+ ob, dvert_array, dvert_tot,
+ vgroup_validmap, vgroup_tot);
if (dvert_array)
MEM_freeN(dvert_array);
}
@@ -1959,11 +1980,12 @@ static int inv_cmp_mdef_vert_weights(const void *a1, const void *a2)
/* Used for limiting the number of influencing bones per vertex when exporting
* skinned meshes. if all_deform_weights is True, limit all deform modifiers
* to max_weights regardless of type, otherwise, only limit the number of influencing bones per vertex*/
-static int vgroup_limit_total_subset(Object *ob,
- const bool *vgroup_validmap,
- const int vgroup_tot,
- const int subset_count,
- const int max_weights)
+static int vgroup_limit_total_subset(
+ Object *ob,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const int subset_count,
+ const int max_weights)
{
MDeformVert *dv, **dvert_array = NULL;
int i, dvert_tot = 0;
@@ -2030,8 +2052,9 @@ static int vgroup_limit_total_subset(Object *ob,
}
-static void vgroup_clean_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot, const int UNUSED(subset_count),
- const float epsilon, const bool keep_single)
+static void vgroup_clean_subset(
+ Object *ob, const bool *vgroup_validmap, const int vgroup_tot, const int UNUSED(subset_count),
+ const float epsilon, const bool keep_single)
{
MDeformVert **dvert_array = NULL;
int dvert_tot = 0;
@@ -2048,16 +2071,18 @@ static void vgroup_clean_subset(Object *ob, const bool *vgroup_validmap, const i
ED_vgroup_parray_mirror_assign(ob, dvert_array, dvert_tot);
}
- ED_vgroup_parray_remove_zero(dvert_array, dvert_tot,
- vgroup_validmap, vgroup_tot,
- epsilon, keep_single);
+ ED_vgroup_parray_remove_zero(
+ dvert_array, dvert_tot,
+ vgroup_validmap, vgroup_tot,
+ epsilon, keep_single);
MEM_freeN(dvert_array);
}
}
-static void vgroup_quantize_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot, const int UNUSED(subset_count),
- const int steps)
+static void vgroup_quantize_subset(
+ Object *ob, const bool *vgroup_validmap, const int vgroup_tot, const int UNUSED(subset_count),
+ const int steps)
{
MDeformVert **dvert_array = NULL;
int dvert_tot = 0;
@@ -2095,11 +2120,12 @@ static void vgroup_quantize_subset(Object *ob, const bool *vgroup_validmap, cons
}
}
-static void dvert_mirror_op(MDeformVert *dvert, MDeformVert *dvert_mirr,
- const char sel, const char sel_mirr,
- const int *flip_map, const int flip_map_len,
- const bool mirror_weights, const bool flip_vgroups, const bool all_vgroups,
- const int act_vgroup)
+static void dvert_mirror_op(
+ MDeformVert *dvert, MDeformVert *dvert_mirr,
+ const char sel, const char sel_mirr,
+ const int *flip_map, const int flip_map_len,
+ const bool mirror_weights, const bool flip_vgroups, const bool all_vgroups,
+ const int act_vgroup)
{
BLI_assert(sel || sel_mirr);
@@ -2158,10 +2184,11 @@ static void dvert_mirror_op(MDeformVert *dvert, MDeformVert *dvert_mirr,
/* TODO, vgroup locking */
/* TODO, face masking */
-void ED_vgroup_mirror(Object *ob,
- const bool mirror_weights, const bool flip_vgroups,
- const bool all_vgroups, const bool use_topology,
- int *r_totmirr, int *r_totfail)
+void ED_vgroup_mirror(
+ Object *ob,
+ const bool mirror_weights, const bool flip_vgroups,
+ const bool all_vgroups, const bool use_topology,
+ int *r_totmirr, int *r_totfail)
{
#define VGROUP_MIRR_OP \
@@ -3282,12 +3309,13 @@ static int vertex_group_mirror_exec(bContext *C, wmOperator *op)
Object *ob = ED_object_context(C);
int totmirr = 0, totfail = 0;
- ED_vgroup_mirror(ob,
- RNA_boolean_get(op->ptr, "mirror_weights"),
- RNA_boolean_get(op->ptr, "flip_group_names"),
- RNA_boolean_get(op->ptr, "all_groups"),
- RNA_boolean_get(op->ptr, "use_topology"),
- &totmirr, &totfail);
+ ED_vgroup_mirror(
+ ob,
+ RNA_boolean_get(op->ptr, "mirror_weights"),
+ RNA_boolean_get(op->ptr, "flip_group_names"),
+ RNA_boolean_get(op->ptr, "all_groups"),
+ RNA_boolean_get(op->ptr, "use_topology"),
+ &totmirr, &totfail);
ED_mesh_report_mirror(op, totmirr, totfail);
@@ -3327,7 +3355,7 @@ static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob_active = ED_object_context(C);
int retval = OPERATOR_CANCELLED;
- FOREACH_SCENE_OBJECT(scene, ob_iter)
+ FOREACH_SCENE_OBJECT_BEGIN(scene, ob_iter)
{
if (ob_iter->type == ob_active->type) {
if (ob_iter != ob_active && ob_iter->data == ob_active->data) {
@@ -3343,7 +3371,7 @@ static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op))
}
}
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
return retval;
}
diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt
index 3cecdccd758..3705ff9d41a 100644
--- a/source/blender/editors/physics/CMakeLists.txt
+++ b/source/blender/editors/physics/CMakeLists.txt
@@ -41,6 +41,7 @@ set(SRC
dynamicpaint_ops.c
particle_boids.c
particle_edit.c
+ particle_edit_undo.c
particle_object.c
physics_fluid.c
physics_ops.c
@@ -49,6 +50,7 @@ set(SRC
rigidbody_object.c
rigidbody_world.c
+ particle_edit_utildefines.h
physics_intern.h
)
diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c
index e068b898345..5d928d69da2 100644
--- a/source/blender/editors/physics/dynamicpaint_ops.c
+++ b/source/blender/editors/physics/dynamicpaint_ops.c
@@ -288,7 +288,6 @@ typedef struct DynamicPaintBakeJob {
struct Main *bmain;
Scene *scene;
- ViewLayer *view_layer;
Depsgraph *depsgraph;
Object *ob;
@@ -365,9 +364,9 @@ static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job)
frame = surface->start_frame;
orig_frame = scene->r.cfra;
scene->r.cfra = (int)frame;
- ED_update_for_newframe(job->bmain, scene, job->view_layer, job->depsgraph);
+ ED_update_for_newframe(job->bmain, job->depsgraph);
- /* Init surface */
+ /* Init surface */
if (!dynamicPaint_createUVSurface(scene, surface, job->progress, job->do_update)) {
job->success = 0;
return;
@@ -391,7 +390,7 @@ static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job)
/* calculate a frame */
scene->r.cfra = (int)frame;
- ED_update_for_newframe(job->bmain, scene, job->view_layer, job->depsgraph);
+ ED_update_for_newframe(job->bmain, job->depsgraph);
if (!dynamicPaint_calculateFrame(surface, job->eval_ctx, scene, cObject, frame)) {
job->success = 0;
return;
@@ -460,7 +459,6 @@ static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op)
DynamicPaintCanvasSettings *canvas;
Object *ob = ED_object_context(C);
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
EvaluationContext *eval_ctx = MEM_mallocN(sizeof(*eval_ctx), "EvaluationContext");
CTX_data_eval_ctx(C, eval_ctx);
@@ -491,7 +489,6 @@ static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op)
DynamicPaintBakeJob *job = MEM_mallocN(sizeof(DynamicPaintBakeJob), "DynamicPaintBakeJob");
job->bmain = CTX_data_main(C);
job->scene = scene;
- job->view_layer = view_layer;
job->depsgraph = CTX_data_depsgraph(C);
job->ob = ob;
job->canvas = canvas;
@@ -508,7 +505,7 @@ static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op)
WM_set_locked_interface(CTX_wm_manager(C), true);
- /* Bake Dynamic Paint */
+ /* Bake Dynamic Paint */
WM_jobs_start(CTX_wm_manager(C), wm_job);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 89dd46681cb..51abb5b2eaa 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -29,7 +29,6 @@
* \ingroup edphys
*/
-
#include <stdlib.h>
#include <math.h>
#include <string.h>
@@ -45,7 +44,7 @@
#include "DNA_space_types.h"
#include "BLI_math.h"
-#include "BLI_lasso.h"
+#include "BLI_lasso_2d.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_kdtree.h"
@@ -71,6 +70,7 @@
#include "ED_physics.h"
#include "ED_mesh.h"
#include "ED_particle.h"
+#include "ED_screen.h"
#include "ED_view3d.h"
#include "GPU_immediate.h"
@@ -86,54 +86,31 @@
#include "physics_intern.h"
-void PE_create_particle_edit(
- const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, Object *ob,
- PointCache *cache, ParticleSystem *psys);
-void PTCacheUndo_clear(PTCacheEdit *edit);
-void recalc_lengths(PTCacheEdit *edit);
-void recalc_emitter_field(Object *ob, ParticleSystem *psys);
-void update_world_cos(Object *ob, PTCacheEdit *edit);
-
-#define KEY_K PTCacheEditKey *key; int k
-#define POINT_P PTCacheEditPoint *point; int p
-#define LOOP_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++)
-#define LOOP_VISIBLE_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!(point->flag & PEP_HIDE))
-#define LOOP_SELECTED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point_is_selected(point))
-#define LOOP_UNSELECTED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!point_is_selected(point))
-#define LOOP_EDITED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_EDIT_RECALC)
-#define LOOP_TAGGED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_TAG)
-#define LOOP_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++)
-#define LOOP_VISIBLE_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if (!(key->flag & PEK_HIDE))
-#define LOOP_SELECTED_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if ((key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE))
-#define LOOP_TAGGED_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if (key->flag & PEK_TAG)
-
-#define KEY_WCO ((key->flag & PEK_USE_WCO) ? key->world_co : key->co)
+#include "particle_edit_utildefines.h"
/**************************** utilities *******************************/
int PE_poll(bContext *C)
{
Scene *scene= CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
- if (!scene || !view_layer || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT))
+ if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) {
return 0;
-
- return (PE_get_current(scene, view_layer, ob) != NULL);
+ }
+ return (PE_get_current(scene, ob) != NULL);
}
int PE_hair_poll(bContext *C)
{
Scene *scene= CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
PTCacheEdit *edit;
- if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT))
+ if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) {
return 0;
-
- edit= PE_get_current(scene, view_layer, ob);
+ }
+ edit= PE_get_current(scene, ob);
return (edit && edit->psys);
}
@@ -154,8 +131,6 @@ void PE_free_ptcache_edit(PTCacheEdit *edit)
if (edit==0) return;
- PTCacheUndo_clear(edit);
-
if (edit->points) {
LOOP_POINTS {
if (point->keys)
@@ -219,7 +194,7 @@ static float pe_brush_size_get(const Scene *UNUSED(scene), ParticleBrushData *br
* note: this function runs on poll, therefor it can runs many times a second
* keep it fast! */
static PTCacheEdit *pe_get_current(
- const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, Object *ob, int create)
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, int create)
{
ParticleEditSettings *pset= PE_settings(scene);
PTCacheEdit *edit = NULL;
@@ -230,7 +205,6 @@ static PTCacheEdit *pe_get_current(
return NULL;
pset->scene = scene;
- pset->view_layer = view_layer;
pset->object = ob;
BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
@@ -259,18 +233,18 @@ static PTCacheEdit *pe_get_current(
if (psys->part && psys->part->type == PART_HAIR) {
if (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED) {
if (create && !psys->pointcache->edit)
- PE_create_particle_edit(eval_ctx, scene, view_layer, ob, pid->cache, NULL);
+ PE_create_particle_edit(eval_ctx, scene, ob, pid->cache, NULL);
edit = pid->cache->edit;
}
else {
if (create && !psys->edit && psys->flag & PSYS_HAIR_DONE)
- PE_create_particle_edit(eval_ctx, scene, view_layer, ob, NULL, psys);
+ PE_create_particle_edit(eval_ctx, scene, ob, NULL, psys);
edit = psys->edit;
}
}
else {
if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit)
- PE_create_particle_edit(eval_ctx, scene, view_layer, ob, pid->cache, psys);
+ PE_create_particle_edit(eval_ctx, scene, ob, pid->cache, psys);
edit = pid->cache->edit;
}
@@ -281,7 +255,7 @@ static PTCacheEdit *pe_get_current(
if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) {
pset->flag |= PE_FADE_TIME;
// NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB;
- PE_create_particle_edit(eval_ctx, scene, view_layer, ob, pid->cache, NULL);
+ PE_create_particle_edit(eval_ctx, scene, ob, pid->cache, NULL);
}
edit = pid->cache->edit;
break;
@@ -290,7 +264,7 @@ static PTCacheEdit *pe_get_current(
if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) {
pset->flag |= PE_FADE_TIME;
// NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB;
- PE_create_particle_edit(eval_ctx, scene, view_layer, ob, pid->cache, NULL);
+ PE_create_particle_edit(eval_ctx, scene, ob, pid->cache, NULL);
}
edit = pid->cache->edit;
break;
@@ -305,14 +279,14 @@ static PTCacheEdit *pe_get_current(
return edit;
}
-PTCacheEdit *PE_get_current(Scene *scene, ViewLayer *view_layer, Object *ob)
+PTCacheEdit *PE_get_current(Scene *scene, Object *ob)
{
- return pe_get_current(NULL, scene, view_layer, ob, 0);
+ return pe_get_current(NULL, scene, ob, 0);
}
PTCacheEdit *PE_create_current(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
- return pe_get_current(eval_ctx, scene, NULL, ob, 1);
+ return pe_get_current(eval_ctx, scene, ob, 1);
}
void PE_current_changed(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
@@ -369,6 +343,7 @@ typedef struct PEData {
DerivedMesh *dm;
PTCacheEdit *edit;
BVHTreeFromMesh shape_bvh;
+ EvaluationContext eval_ctx;
const int *mval;
rcti *rect;
@@ -401,24 +376,22 @@ static void PE_set_data(bContext *C, PEData *data)
data->scene = CTX_data_scene(C);
data->view_layer = CTX_data_view_layer(C);
data->ob = CTX_data_active_object(C);
- data->edit = PE_get_current(data->scene, data->view_layer, data->ob);
+ CTX_data_eval_ctx(C, &data->eval_ctx);
+ data->edit = PE_get_current(data->scene, data->ob);
}
static void PE_set_view3d_data(bContext *C, PEData *data)
{
PE_set_data(C, data);
- view3d_set_viewcontext(C, &data->vc);
+ ED_view3d_viewcontext_init(C, &data->vc);
if (V3D_IS_ZBUF(data->vc.v3d)) {
if (data->vc.v3d->flag & V3D_INVALID_BACKBUF) {
- EvaluationContext eval_ctx;
- CTX_data_eval_ctx(C, &eval_ctx);
-
/* needed or else the draw matrix can be incorrect */
view3d_operator_needs_opengl(C);
- ED_view3d_backbuf_validate(&eval_ctx, &data->vc);
+ ED_view3d_backbuf_validate(&data->eval_ctx, &data->vc);
/* we may need to force an update here by setting the rv3d as dirty
* for now it seems ok, but take care!:
* rv3d->depths->dirty = 1; */
@@ -1163,15 +1136,12 @@ void recalc_emitter_field(Object *ob, ParticleSystem *psys)
BLI_kdtree_balance(edit->emitter_field);
}
-static void PE_update_selection(const bContext *C, Scene *scene, ViewLayer *view_layer, Object *ob, int useflag)
+static void PE_update_selection(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, int useflag)
{
- PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
HairKey *hkey;
- EvaluationContext eval_ctx;
POINT_P; KEY_K;
- CTX_data_eval_ctx(C, &eval_ctx);
-
/* flag all particles to be updated if not using flag */
if (!useflag)
LOOP_POINTS
@@ -1187,7 +1157,7 @@ static void PE_update_selection(const bContext *C, Scene *scene, ViewLayer *view
}
}
- psys_cache_edit_paths(&eval_ctx, scene, ob, edit, CFRA, G.is_rendering);
+ psys_cache_edit_paths(eval_ctx, scene, ob, edit, CFRA, G.is_rendering);
/* disable update flag */
@@ -1273,12 +1243,12 @@ static void update_velocities(PTCacheEdit *edit)
}
}
-void PE_update_object(const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, Object *ob, int useflag)
+void PE_update_object(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, int useflag)
{
/* use this to do partial particle updates, not usable when adding or
* removing, then a full redo is necessary and calling this may crash */
ParticleEditSettings *pset= PE_settings(scene);
- PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
POINT_P;
if (!edit)
@@ -1312,6 +1282,8 @@ void PE_update_object(const EvaluationContext *eval_ctx, Scene *scene, ViewLayer
if (edit->psys)
edit->psys->flag &= ~PSYS_HAIR_UPDATED;
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
/************************************************/
@@ -1413,9 +1385,10 @@ static void select_action_apply(PTCacheEditPoint *point, PTCacheEditKey *key, in
static int pe_select_all_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit= PE_get_current(scene, ob);
POINT_P; KEY_K;
int action = RNA_enum_get(op->ptr, "action");
@@ -1438,7 +1411,7 @@ static int pe_select_all_exec(bContext *C, wmOperator *op)
}
}
- PE_update_selection(C, scene, view_layer, ob, 1);
+ PE_update_selection(&eval_ctx, scene, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -1467,9 +1440,8 @@ int PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselec
{
PEData data;
Scene *scene= CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit= PE_get_current(scene, ob);
POINT_P; KEY_K;
if (!PE_start_edit(edit))
@@ -1496,7 +1468,7 @@ int PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselec
else
for_mouse_hit_keys(&data, toggle_key_select, 1);
- PE_update_selection(C, scene, view_layer, ob, 1);
+ PE_update_selection(&data.eval_ctx, scene, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -1537,7 +1509,7 @@ static int select_roots_exec(bContext *C, wmOperator *op)
data.select_action = action;
foreach_point(&data, select_root);
- PE_update_selection(C, data.scene, data.view_layer, data.ob, 1);
+ PE_update_selection(&data.eval_ctx, data.scene, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -1602,7 +1574,7 @@ static int select_tips_exec(bContext *C, wmOperator *op)
data.select_action = action;
foreach_point(&data, select_tip);
- PE_update_selection(C, data.scene, data.view_layer, data.ob, 1);
+ PE_update_selection(&data.eval_ctx, data.scene, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -1641,7 +1613,6 @@ static int select_random_exec(bContext *C, wmOperator *op)
PEData data;
int type;
Scene *scene;
- ViewLayer *view_layer;
Object *ob;
/* used by LOOP_VISIBLE_POINTS, LOOP_VISIBLE_KEYS and LOOP_KEYS */
@@ -1661,9 +1632,8 @@ static int select_random_exec(bContext *C, wmOperator *op)
PE_set_data(C, &data);
data.select_action = SEL_SELECT;
scene = CTX_data_scene(C);
- view_layer = CTX_data_view_layer(C);
ob = CTX_data_active_object(C);
- edit = PE_get_current(scene, view_layer, ob);
+ edit = PE_get_current(scene, ob);
rng = BLI_rng_new_srandom(seed);
@@ -1688,7 +1658,7 @@ static int select_random_exec(bContext *C, wmOperator *op)
BLI_rng_free(rng);
- PE_update_selection(C, data.scene, data.view_layer, data.ob, 1);
+ PE_update_selection(&data.eval_ctx, data.scene, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -1732,7 +1702,7 @@ static int select_linked_exec(bContext *C, wmOperator *op)
data.select= !RNA_boolean_get(op->ptr, "deselect");
for_mouse_hit_keys(&data, select_keys, 1); /* nearest only */
- PE_update_selection(C, data.scene, data.view_layer, data.ob, 1);
+ PE_update_selection(&data.eval_ctx, data.scene, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -1780,9 +1750,8 @@ void PE_deselect_all_visible(PTCacheEdit *edit)
int PE_border_select(bContext *C, rcti *rect, bool select, bool extend)
{
Scene *scene= CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit= PE_get_current(scene, ob);
PEData data;
if (!PE_start_edit(edit))
@@ -1797,7 +1766,7 @@ int PE_border_select(bContext *C, rcti *rect, bool select, bool extend)
for_mouse_hit_keys(&data, select_key, 0);
- PE_update_selection(C, scene, view_layer, ob, 1);
+ PE_update_selection(&data.eval_ctx, scene, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -1808,9 +1777,8 @@ int PE_border_select(bContext *C, rcti *rect, bool select, bool extend)
int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad)
{
Scene *scene= CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit= PE_get_current(scene, ob);
PEData data;
if (!PE_start_edit(edit))
@@ -1823,7 +1791,7 @@ int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad)
for_mouse_hit_keys(&data, select_key, 0);
- PE_update_selection(C, scene, view_layer, ob, 1);
+ PE_update_selection(&data.eval_ctx, scene, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -1834,11 +1802,10 @@ int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad)
int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool extend, bool select)
{
Scene *scene= CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
ARegion *ar= CTX_wm_region(C);
ParticleEditSettings *pset= PE_settings(scene);
- PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
ParticleSystem *psys = edit->psys;
ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
POINT_P; KEY_K;
@@ -1912,7 +1879,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool
}
}
- PE_update_selection(C, scene, view_layer, ob, 1);
+ PE_update_selection(&data.eval_ctx, scene, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -1924,10 +1891,13 @@ static int hide_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_active_object(C);
Scene *scene= CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ PTCacheEdit *edit= PE_get_current(scene, ob);
POINT_P; KEY_K;
-
+
+
if (RNA_enum_get(op->ptr, "unselected")) {
LOOP_UNSELECTED_POINTS {
point->flag |= PEP_HIDE;
@@ -1947,7 +1917,7 @@ static int hide_exec(bContext *C, wmOperator *op)
}
}
- PE_update_selection(C, scene, view_layer, ob, 1);
+ PE_update_selection(&eval_ctx, scene, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -1977,8 +1947,9 @@ static int reveal_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_active_object(C);
Scene *scene= CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+ PTCacheEdit *edit= PE_get_current(scene, ob);
const bool select = RNA_boolean_get(op->ptr, "select");
POINT_P; KEY_K;
@@ -1993,7 +1964,7 @@ static int reveal_exec(bContext *C, wmOperator *op)
}
}
- PE_update_selection(C, scene, view_layer, ob, 1);
+ PE_update_selection(&eval_ctx, scene, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -2055,7 +2026,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
PE_set_data(C, &data);
foreach_point(&data, select_less_keys);
- PE_update_selection(C, data.scene, data.view_layer, data.ob, 1);
+ PE_update_selection(&data.eval_ctx, data.scene, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -2117,7 +2088,7 @@ static int select_more_exec(bContext *C, wmOperator *UNUSED(op))
PE_set_data(C, &data);
foreach_point(&data, select_more_keys);
- PE_update_selection(C, data.scene, data.view_layer, data.ob, 1);
+ PE_update_selection(&data.eval_ctx, data.scene, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -2220,7 +2191,7 @@ static int rekey_exec(bContext *C, wmOperator *op)
foreach_selected_point(&data, rekey_particle);
recalc_lengths(data.edit);
- PE_update_object(&eval_ctx, data.scene, data.view_layer, data.ob, 1);
+ PE_update_object(&eval_ctx, data.scene, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
return OPERATOR_FINISHED;
@@ -2245,9 +2216,9 @@ void PARTICLE_OT_rekey(wmOperatorType *ot)
RNA_def_int(ot->srna, "keys_number", 2, 2, INT_MAX, "Number of Keys", "", 2, 100);
}
-static void rekey_particle_to_time(const bContext *C, Scene *scene, ViewLayer *view_layer, Object *ob, int pa_index, float path_time)
+static void rekey_particle_to_time(const bContext *C, Scene *scene, Object *ob, int pa_index, float path_time)
{
- PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit= PE_get_current(scene, ob);
ParticleSystem *psys;
ParticleSimulationData sim = {0};
ParticleData *pa;
@@ -2561,7 +2532,7 @@ static int subdivide_exec(bContext *C, wmOperator *UNUSED(op))
foreach_point(&data, subdivide_particle);
recalc_lengths(data.edit);
- PE_update_object(&eval_ctx, data.scene, data.view_layer, data.ob, 1);
+ PE_update_object(&eval_ctx, data.scene, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
return OPERATOR_FINISHED;
@@ -2587,9 +2558,8 @@ void PARTICLE_OT_subdivide(wmOperatorType *ot)
static int remove_doubles_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit= PE_get_current(scene, ob);
ParticleSystem *psys = edit->psys;
ParticleSystemModifierData *psmd;
KDTree *tree;
@@ -2680,10 +2650,9 @@ void PARTICLE_OT_remove_doubles(wmOperatorType *ot)
static int weight_set_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
ParticleEditSettings *pset= PE_settings(scene);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit= PE_get_current(scene, ob);
ParticleSystem *psys = edit->psys;
POINT_P;
KEY_K;
@@ -2840,11 +2809,12 @@ void PARTICLE_OT_delete(wmOperatorType *ot)
/*************************** mirror operator **************************/
-static void PE_mirror_x(Scene *scene, ViewLayer *view_layer, Object *ob, int tagged)
+static void PE_mirror_x(
+ Scene *scene, Object *ob, int tagged)
{
Mesh *me= (Mesh *)(ob->data);
ParticleSystemModifierData *psmd;
- PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
ParticleSystem *psys = edit->psys;
ParticleData *pa, *newpa, *new_pars;
PTCacheEditPoint *newpoint, *new_points;
@@ -2991,11 +2961,10 @@ static void PE_mirror_x(Scene *scene, ViewLayer *view_layer, Object *ob, int tag
static int mirror_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene= CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit= PE_get_current(scene, ob);
- PE_mirror_x(scene, view_layer, ob, 0);
+ PE_mirror_x(scene, ob, 0);
update_world_cos(ob, edit);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
@@ -3132,7 +3101,7 @@ static void brush_cut(PEData *data, int pa_index)
edit->points[pa_index].flag |= PEP_TAG;
}
else {
- rekey_particle_to_time(data->context, data->scene, data->view_layer, ob, pa_index, cut_time);
+ rekey_particle_to_time(data->context, data->scene, ob, pa_index, cut_time);
edit->points[pa_index].flag |= PEP_EDIT_RECALC;
}
}
@@ -3787,7 +3756,7 @@ static int brush_edit_init(bContext *C, wmOperator *op)
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
ParticleEditSettings *pset= PE_settings(scene);
- PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit= PE_get_current(scene, ob);
ARegion *ar= CTX_wm_region(C);
BrushEdit *bedit;
float min[3], max[3];
@@ -3821,7 +3790,6 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
{
BrushEdit *bedit= op->customdata;
Scene *scene= bedit->scene;
- ViewLayer *view_layer = bedit->view_layer;
Object *ob= bedit->ob;
PTCacheEdit *edit= bedit->edit;
ParticleEditSettings *pset= PE_settings(scene);
@@ -3865,6 +3833,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
(sqrtf(dx * dx + dy * dy) > pset->brush[PE_BRUSH_ADD].step) : (dx != 0 || dy != 0)) || bedit->first)
{
PEData data= bedit->data;
+ data.context = C; // TODO(mai): why isnt this set in bedit->data?
view3d_operator_needs_opengl(C);
selected= (short)count_selected_keys(scene, edit);
@@ -4015,14 +3984,14 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_CUT) && (added || removed)) {
if (pset->brushtype == PE_BRUSH_ADD && pe_x_mirror(ob))
- PE_mirror_x(scene, view_layer, ob, 1);
+ PE_mirror_x(scene, ob, 1);
update_world_cos(ob, edit);
psys_free_path_cache(NULL, edit);
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
else {
- PE_update_object(&eval_ctx, scene, view_layer, ob, 1);
+ PE_update_object(&eval_ctx, scene, ob, 1);
}
}
@@ -4238,7 +4207,7 @@ static void shape_cut(PEData *data, int pa_index)
edit->points[pa_index].flag |= PEP_TAG;
}
else {
- rekey_particle_to_time(data->context, data->scene, data->view_layer, ob, pa_index, cut_time);
+ rekey_particle_to_time(data->context, data->scene, ob, pa_index, cut_time);
edit->points[pa_index].flag |= PEP_EDIT_RECALC;
}
}
@@ -4247,10 +4216,9 @@ static void shape_cut(PEData *data, int pa_index)
static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = CTX_data_active_object(C);
ParticleEditSettings *pset = PE_settings(scene);
- PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
Object *shapeob = pset->shape_object;
int selected = count_selected_keys(scene, edit);
int lock_root = pset->flag & PE_LOCK_FIRST;
@@ -4258,9 +4226,6 @@ static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
if (!PE_start_edit(edit))
return OPERATOR_CANCELLED;
- EvaluationContext eval_ctx;
- CTX_data_eval_ctx(C, &eval_ctx);
-
/* disable locking temporatily for disconnected hair */
if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
pset->flag &= ~PE_LOCK_FIRST;
@@ -4289,7 +4254,7 @@ static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
else {
- PE_update_object(&eval_ctx, scene, view_layer, ob, 1);
+ PE_update_object(&data.eval_ctx, scene, ob, 1);
}
if (edit->psys) {
@@ -4323,299 +4288,12 @@ void PARTICLE_OT_shape_cut(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
}
-/*********************** undo ***************************/
-
-static void free_PTCacheUndo(PTCacheUndo *undo)
-{
- PTCacheEditPoint *point;
- int i;
-
- for (i=0, point=undo->points; i<undo->totpoint; i++, point++) {
- if (undo->particles && (undo->particles + i)->hair)
- MEM_freeN((undo->particles + i)->hair);
- if (point->keys)
- MEM_freeN(point->keys);
- }
- if (undo->points)
- MEM_freeN(undo->points);
-
- if (undo->particles)
- MEM_freeN(undo->particles);
-
- BKE_ptcache_free_mem(&undo->mem_cache);
-}
-
-static void make_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo)
-{
- PTCacheEditPoint *point;
- int i;
-
- undo->totpoint= edit->totpoint;
-
- if (edit->psys) {
- ParticleData *pa;
-
- pa= undo->particles= MEM_dupallocN(edit->psys->particles);
-
- for (i=0; i<edit->totpoint; i++, pa++)
- pa->hair= MEM_dupallocN(pa->hair);
-
- undo->psys_flag = edit->psys->flag;
- }
- else {
- PTCacheMem *pm;
-
- BLI_duplicatelist(&undo->mem_cache, &edit->pid.cache->mem_cache);
- pm = undo->mem_cache.first;
-
- for (; pm; pm=pm->next) {
- for (i=0; i<BPHYS_TOT_DATA; i++)
- pm->data[i] = MEM_dupallocN(pm->data[i]);
- }
- }
-
- point= undo->points = MEM_dupallocN(edit->points);
- undo->totpoint = edit->totpoint;
-
- for (i=0; i<edit->totpoint; i++, point++) {
- point->keys= MEM_dupallocN(point->keys);
- /* no need to update edit key->co & key->time pointers here */
- }
-}
-
-static void get_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo)
-{
- ParticleSystem *psys = edit->psys;
- ParticleData *pa;
- HairKey *hkey;
- POINT_P; KEY_K;
-
- LOOP_POINTS {
- if (psys && psys->particles[p].hair)
- MEM_freeN(psys->particles[p].hair);
-
- if (point->keys)
- MEM_freeN(point->keys);
- }
- if (psys && psys->particles)
- MEM_freeN(psys->particles);
- if (edit->points)
- MEM_freeN(edit->points);
- if (edit->mirror_cache) {
- MEM_freeN(edit->mirror_cache);
- edit->mirror_cache= NULL;
- }
-
- edit->points= MEM_dupallocN(undo->points);
- edit->totpoint = undo->totpoint;
-
- LOOP_POINTS {
- point->keys= MEM_dupallocN(point->keys);
- }
-
- if (psys) {
- psys->particles= MEM_dupallocN(undo->particles);
-
- psys->totpart= undo->totpoint;
-
- LOOP_POINTS {
- pa = psys->particles + p;
- hkey= pa->hair = MEM_dupallocN(pa->hair);
-
- LOOP_KEYS {
- key->co= hkey->co;
- key->time= &hkey->time;
- hkey++;
- }
- }
-
- psys->flag = undo->psys_flag;
- }
- else {
- PTCacheMem *pm;
- int i;
-
- BKE_ptcache_free_mem(&edit->pid.cache->mem_cache);
-
- BLI_duplicatelist(&edit->pid.cache->mem_cache, &undo->mem_cache);
-
- pm = edit->pid.cache->mem_cache.first;
-
- for (; pm; pm=pm->next) {
- for (i=0; i<BPHYS_TOT_DATA; i++)
- pm->data[i] = MEM_dupallocN(pm->data[i]);
-
- BKE_ptcache_mem_pointers_init(pm);
-
- LOOP_POINTS {
- LOOP_KEYS {
- if ((int)key->ftime == (int)pm->frame) {
- key->co = pm->cur[BPHYS_DATA_LOCATION];
- key->vel = pm->cur[BPHYS_DATA_VELOCITY];
- key->rot = pm->cur[BPHYS_DATA_ROTATION];
- key->time = &key->ftime;
- }
- }
- BKE_ptcache_mem_pointers_incr(pm);
- }
- }
- }
-}
-
-void PE_undo_push(Scene *scene, ViewLayer *view_layer, const char *str)
-{
- PTCacheEdit *edit= PE_get_current(scene, view_layer, OBACT(view_layer));
- PTCacheUndo *undo;
- int nr;
-
- if (!edit) return;
-
- /* remove all undos after (also when curundo==NULL) */
- while (edit->undo.last != edit->curundo) {
- undo= edit->undo.last;
- BLI_remlink(&edit->undo, undo);
- free_PTCacheUndo(undo);
- MEM_freeN(undo);
- }
-
- /* make new */
- edit->curundo= undo= MEM_callocN(sizeof(PTCacheUndo), "particle undo file");
- BLI_strncpy(undo->name, str, sizeof(undo->name));
- BLI_addtail(&edit->undo, undo);
-
- /* and limit amount to the maximum */
- nr= 0;
- undo= edit->undo.last;
- while (undo) {
- nr++;
- if (nr==U.undosteps) break;
- undo= undo->prev;
- }
- if (undo) {
- while (edit->undo.first != undo) {
- PTCacheUndo *first= edit->undo.first;
- BLI_remlink(&edit->undo, first);
- free_PTCacheUndo(first);
- MEM_freeN(first);
- }
- }
-
- /* copy */
- make_PTCacheUndo(edit, edit->curundo);
-}
-
-void PE_undo_step(Scene *scene, ViewLayer *view_layer, int step)
-{
- PTCacheEdit *edit= PE_get_current(scene, view_layer, OBACT(view_layer));
-
- if (!edit) return;
-
- if (step==0) {
- get_PTCacheUndo(edit, edit->curundo);
- }
- else if (step==1) {
-
- if (edit->curundo==NULL || edit->curundo->prev==NULL) {
- /* pass */
- }
- else {
- if (G.debug & G_DEBUG) printf("undo %s\n", edit->curundo->name);
- edit->curundo= edit->curundo->prev;
- get_PTCacheUndo(edit, edit->curundo);
- }
- }
- else {
- /* curundo has to remain current situation! */
-
- if (edit->curundo==NULL || edit->curundo->next==NULL) {
- /* pass */
- }
- else {
- get_PTCacheUndo(edit, edit->curundo->next);
- edit->curundo= edit->curundo->next;
- if (G.debug & G_DEBUG) printf("redo %s\n", edit->curundo->name);
- }
- }
-
- DEG_id_tag_update(&OBACT(view_layer)->id, OB_RECALC_DATA);
-}
-
-bool PE_undo_is_valid(Scene *scene, ViewLayer *view_layer)
-{
- PTCacheEdit *edit= PE_get_current(scene, view_layer, OBACT(view_layer));
-
- if (edit) {
- return (edit->undo.last != edit->undo.first);
- }
- return 0;
-}
-
-void PTCacheUndo_clear(PTCacheEdit *edit)
-{
- PTCacheUndo *undo;
-
- if (edit==NULL) return;
-
- undo= edit->undo.first;
- while (undo) {
- free_PTCacheUndo(undo);
- undo= undo->next;
- }
- BLI_freelistN(&edit->undo);
- edit->curundo= NULL;
-}
-
-void PE_undo(Scene *scene, ViewLayer *view_layer)
-{
- PE_undo_step(scene, view_layer, 1);
-}
-
-void PE_redo(Scene *scene, ViewLayer *view_layer)
-{
- PE_undo_step(scene, view_layer, -1);
-}
-
-void PE_undo_number(Scene *scene, ViewLayer *view_layer, int nr)
-{
- PTCacheEdit *edit= PE_get_current(scene, view_layer, OBACT(view_layer));
- PTCacheUndo *undo;
- int a=0;
-
- for (undo= edit->undo.first; undo; undo= undo->next, a++) {
- if (a==nr) break;
- }
- edit->curundo= undo;
- PE_undo_step(scene, view_layer, 0);
-}
-
-
-/* get name of undo item, return null if no item with this index */
-/* if active pointer, set it to 1 if true */
-const char *PE_undo_get_name(Scene *scene, ViewLayer *view_layer, int nr, bool *r_active)
-{
- PTCacheEdit *edit= PE_get_current(scene, view_layer, OBACT(view_layer));
- PTCacheUndo *undo;
-
- if (r_active) *r_active = false;
-
- if (edit) {
- undo= BLI_findlink(&edit->undo, nr);
- if (undo) {
- if (r_active && (undo == edit->curundo)) {
- *r_active = true;
- }
- return undo->name;
- }
- }
- return NULL;
-}
-
/************************ utilities ******************************/
int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3])
{
Object *ob= OBACT(view_layer);
- PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit= PE_get_current(scene, ob);
ParticleSystem *psys;
ParticleSystemModifierData *psmd = NULL;
POINT_P; KEY_K;
@@ -4653,7 +4331,7 @@ int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3])
/* initialize needed data for bake edit */
void PE_create_particle_edit(
- const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, Object *ob, PointCache *cache, ParticleSystem *psys)
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
{
PTCacheEdit *edit;
ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL;
@@ -4754,10 +4432,8 @@ void PE_create_particle_edit(
recalc_lengths(edit);
if (psys && !cache)
recalc_emitter_field(ob, psys);
- PE_update_object(eval_ctx, scene, view_layer, ob, 1);
- PTCacheUndo_clear(edit);
- PE_undo_push(scene, view_layer, "Original");
+ PE_update_object(eval_ctx, scene, ob, 1);
}
}
@@ -4784,9 +4460,6 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
const int mode_flag = OB_MODE_PARTICLE_EDIT;
const bool is_mode_set = (ob->mode & mode_flag) != 0;
- BKE_report(op->reports, RPT_INFO, "Particles are changing, editing is not possible");
- return OPERATOR_CANCELLED;
-
if (!is_mode_set) {
if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
return OPERATOR_CANCELLED;
@@ -4815,6 +4488,8 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
}
+ // ED_workspace_object_mode_sync_from_object(wm, workspace, ob);
+
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
return OPERATOR_FINISHED;
@@ -4967,8 +4642,10 @@ static int unify_length_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = CTX_data_active_object(C);
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ PTCacheEdit *edit = PE_get_current(scene, ob);
float average_length = calculate_average_length(edit);
if (average_length == 0.0f) {
@@ -4976,10 +4653,8 @@ static int unify_length_exec(bContext *C, wmOperator *UNUSED(op))
}
scale_points_to_length(edit, average_length);
- EvaluationContext eval_ctx;
- CTX_data_eval_ctx(C, &eval_ctx);
- PE_update_object(&eval_ctx, scene, view_layer, ob, 1);
+ PE_update_object(&eval_ctx, scene, ob, 1);
if (edit->psys) {
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
}
diff --git a/source/blender/editors/physics/particle_edit_undo.c b/source/blender/editors/physics/particle_edit_undo.c
new file mode 100644
index 00000000000..5199b1c54fa
--- /dev/null
+++ b/source/blender/editors/physics/particle_edit_undo.c
@@ -0,0 +1,301 @@
+/*
+ * ***** 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) 2007 by Janne Karhu.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/physics/particle_edit_undo.c
+ * \ingroup edphys
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <assert.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_context.h"
+#include "BKE_undo_system.h"
+
+#include "DEG_depsgraph.h"
+
+#include "ED_object.h"
+#include "ED_particle.h"
+#include "ED_physics.h"
+
+#include "particle_edit_utildefines.h"
+
+#include "physics_intern.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Undo Conversion
+ * \{ */
+
+static void undoptcache_from_editcache(PTCacheUndo *undo, PTCacheEdit *edit)
+{
+ PTCacheEditPoint *point;
+ int i;
+
+ size_t mem_used_prev = MEM_get_memory_in_use();
+
+ undo->totpoint= edit->totpoint;
+
+ if (edit->psys) {
+ ParticleData *pa;
+
+ pa= undo->particles= MEM_dupallocN(edit->psys->particles);
+
+ for (i=0; i<edit->totpoint; i++, pa++) {
+ pa->hair= MEM_dupallocN(pa->hair);
+ }
+
+ undo->psys_flag = edit->psys->flag;
+ }
+ else {
+ PTCacheMem *pm;
+
+ BLI_duplicatelist(&undo->mem_cache, &edit->pid.cache->mem_cache);
+ pm = undo->mem_cache.first;
+
+ for (; pm; pm=pm->next) {
+ for (i=0; i<BPHYS_TOT_DATA; i++) {
+ pm->data[i] = MEM_dupallocN(pm->data[i]);
+ }
+ }
+ }
+
+ point= undo->points = MEM_dupallocN(edit->points);
+ undo->totpoint = edit->totpoint;
+
+ for (i=0; i<edit->totpoint; i++, point++) {
+ point->keys= MEM_dupallocN(point->keys);
+ /* no need to update edit key->co & key->time pointers here */
+ }
+
+ size_t mem_used_curr = MEM_get_memory_in_use();
+
+ undo->undo_size = mem_used_prev < mem_used_curr ? mem_used_curr - mem_used_prev : sizeof(PTCacheUndo);
+}
+
+static void undoptcache_to_editcache(PTCacheUndo *undo, PTCacheEdit *edit)
+{
+ ParticleSystem *psys = edit->psys;
+ ParticleData *pa;
+ HairKey *hkey;
+ POINT_P; KEY_K;
+
+ LOOP_POINTS {
+ if (psys && psys->particles[p].hair) {
+ MEM_freeN(psys->particles[p].hair);
+ }
+
+ if (point->keys) {
+ MEM_freeN(point->keys);
+ }
+ }
+ if (psys && psys->particles) {
+ MEM_freeN(psys->particles);
+ }
+ if (edit->points) {
+ MEM_freeN(edit->points);
+ }
+ if (edit->mirror_cache) {
+ MEM_freeN(edit->mirror_cache);
+ edit->mirror_cache= NULL;
+ }
+
+ edit->points= MEM_dupallocN(undo->points);
+ edit->totpoint = undo->totpoint;
+
+ LOOP_POINTS {
+ point->keys= MEM_dupallocN(point->keys);
+ }
+
+ if (psys) {
+ psys->particles= MEM_dupallocN(undo->particles);
+
+ psys->totpart= undo->totpoint;
+
+ LOOP_POINTS {
+ pa = psys->particles + p;
+ hkey= pa->hair = MEM_dupallocN(pa->hair);
+
+ LOOP_KEYS {
+ key->co= hkey->co;
+ key->time= &hkey->time;
+ hkey++;
+ }
+ }
+
+ psys->flag = undo->psys_flag;
+ }
+ else {
+ PTCacheMem *pm;
+ int i;
+
+ BKE_ptcache_free_mem(&edit->pid.cache->mem_cache);
+
+ BLI_duplicatelist(&edit->pid.cache->mem_cache, &undo->mem_cache);
+
+ pm = edit->pid.cache->mem_cache.first;
+
+ for (; pm; pm=pm->next) {
+ for (i = 0; i < BPHYS_TOT_DATA; i++) {
+ pm->data[i] = MEM_dupallocN(pm->data[i]);
+ }
+ BKE_ptcache_mem_pointers_init(pm);
+
+ LOOP_POINTS {
+ LOOP_KEYS {
+ if ((int)key->ftime == (int)pm->frame) {
+ key->co = pm->cur[BPHYS_DATA_LOCATION];
+ key->vel = pm->cur[BPHYS_DATA_VELOCITY];
+ key->rot = pm->cur[BPHYS_DATA_ROTATION];
+ key->time = &key->ftime;
+ }
+ }
+ BKE_ptcache_mem_pointers_incr(pm);
+ }
+ }
+ }
+}
+
+static void undoptcache_free_data(PTCacheUndo *undo)
+{
+ PTCacheEditPoint *point;
+ int i;
+
+ for (i = 0, point=undo->points; i < undo->totpoint; i++, point++) {
+ if (undo->particles && (undo->particles + i)->hair) {
+ MEM_freeN((undo->particles + i)->hair);
+ }
+ if (point->keys) {
+ MEM_freeN(point->keys);
+ }
+ }
+ if (undo->points) {
+ MEM_freeN(undo->points);
+ }
+ if (undo->particles) {
+ MEM_freeN(undo->particles);
+ }
+ BKE_ptcache_free_mem(&undo->mem_cache);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Implements ED Undo System
+ * \{ */
+
+typedef struct ParticleUndoStep {
+ UndoStep step;
+ UndoRefID_Scene scene_ref;
+ UndoRefID_Object object_ref;
+ PTCacheUndo data;
+} ParticleUndoStep;
+
+static bool particle_undosys_poll(struct bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+
+ return (edit != NULL);
+}
+
+static bool particle_undosys_step_encode(struct bContext *C, UndoStep *us_p)
+{
+ ParticleUndoStep *us = (ParticleUndoStep *)us_p;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ us->scene_ref.ptr = CTX_data_scene(C);
+ us->object_ref.ptr = OBACT(view_layer);
+ PTCacheEdit *edit = PE_get_current(us->scene_ref.ptr, us->object_ref.ptr);
+ undoptcache_from_editcache(&us->data, edit);
+ return true;
+}
+
+static void particle_undosys_step_decode(struct bContext *C, UndoStep *us_p, int UNUSED(dir))
+{
+ /* TODO(campbell): undo_system: use low-level API to set mode. */
+ ED_object_mode_set(C, OB_MODE_PARTICLE_EDIT);
+ BLI_assert(particle_undosys_poll(C));
+
+ ParticleUndoStep *us = (ParticleUndoStep *)us_p;
+ Scene *scene = us->scene_ref.ptr;
+ Object *ob = us->object_ref.ptr;
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ if (edit) {
+ undoptcache_to_editcache(&us->data, edit);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+ else {
+ BLI_assert(0);
+ }
+}
+
+static void particle_undosys_step_free(UndoStep *us_p)
+{
+ ParticleUndoStep *us = (ParticleUndoStep *)us_p;
+ undoptcache_free_data(&us->data);
+}
+
+static void particle_undosys_foreach_ID_ref(
+ UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+{
+ ParticleUndoStep *us = (ParticleUndoStep *)us_p;
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->scene_ref));
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->object_ref));
+}
+
+/* Export for ED_undo_sys. */
+void ED_particle_undosys_type(UndoType *ut)
+{
+ ut->name = "Edit Particle";
+ ut->poll = particle_undosys_poll;
+ ut->step_encode = particle_undosys_step_encode;
+ ut->step_decode = particle_undosys_step_decode;
+ ut->step_free = particle_undosys_step_free;
+
+ ut->step_foreach_ID_ref = particle_undosys_foreach_ID_ref;
+
+ ut->mode = BKE_UNDOTYPE_MODE_STORE;
+ ut->use_context = true;
+
+ ut->step_size = sizeof(ParticleUndoStep);
+}
+
+/** \} */
diff --git a/source/blender/editors/physics/particle_edit_utildefines.h b/source/blender/editors/physics/particle_edit_utildefines.h
new file mode 100644
index 00000000000..7608b885459
--- /dev/null
+++ b/source/blender/editors/physics/particle_edit_utildefines.h
@@ -0,0 +1,50 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by Janne Karhu.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/physics/particle_edit_utildefines.h
+ * \ingroup edphys
+ */
+
+#ifndef __PARTICLE_EDIT_UTILDEFNIES_H__
+#define __PARTICLE_EDIT_UTILDEFNIES_H__
+
+#define KEY_K PTCacheEditKey *key; int k
+#define POINT_P PTCacheEditPoint *point; int p
+#define LOOP_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++)
+#define LOOP_VISIBLE_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!(point->flag & PEP_HIDE))
+#define LOOP_SELECTED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point_is_selected(point))
+#define LOOP_UNSELECTED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!point_is_selected(point))
+#define LOOP_EDITED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_EDIT_RECALC)
+#define LOOP_TAGGED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_TAG)
+#define LOOP_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++)
+#define LOOP_VISIBLE_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if (!(key->flag & PEK_HIDE))
+#define LOOP_SELECTED_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if ((key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE))
+#define LOOP_TAGGED_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if (key->flag & PEK_TAG)
+
+#define KEY_WCO ((key->flag & PEK_USE_WCO) ? key->world_co : key->co)
+
+#endif /* __PARTICLE_EDIT_UTILDEFNIES_H__ */
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 1536c15525f..1fae5b70aff 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -69,32 +69,9 @@
#include "UI_resources.h"
-#include "physics_intern.h"
+#include "particle_edit_utildefines.h"
-extern void PE_create_particle_edit(const bContext *C, Scene *scene, ViewLayer *view_layer, Object *ob, PointCache *cache, ParticleSystem *psys);
-extern void PTCacheUndo_clear(PTCacheEdit *edit);
-extern void recalc_lengths(PTCacheEdit *edit);
-extern void recalc_emitter_field(Object *ob, ParticleSystem *psys);
-extern void update_world_cos(Object *ob, PTCacheEdit *edit);
-
-#define KEY_K PTCacheEditKey *key; int k
-#define POINT_P PTCacheEditPoint *point; int p
-#define LOOP_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++)
-#if 0
-#define LOOP_VISIBLE_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!(point->flag & PEP_HIDE))
-#define LOOP_SELECTED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point_is_selected(point))
-#define LOOP_UNSELECTED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!point_is_selected(point))
-#define LOOP_EDITED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_EDIT_RECALC)
-#define LOOP_TAGGED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_TAG)
-#endif
-#define LOOP_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++)
-#if 0
-#define LOOP_VISIBLE_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if (!(key->flag & PEK_HIDE))
-#define LOOP_SELECTED_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if ((key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE))
-#define LOOP_TAGGED_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if (key->flag & PEK_TAG)
-
-#define KEY_WCO (key->flag & PEK_USE_WCO ? key->world_co : key->co)
-#endif
+#include "physics_intern.h"
static float I[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}};
@@ -569,7 +546,7 @@ void PARTICLE_OT_dupliob_move_down(wmOperatorType *ot)
/************************ connect/disconnect hair operators *********************/
static void disconnect_hair(
- const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ const EvaluationContext *eval_ctx, Scene *scene,
Object *ob, ParticleSystem *psys)
{
ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
@@ -616,13 +593,12 @@ static void disconnect_hair(
if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_PUFF))
pset->brushtype = PE_BRUSH_NONE;
- PE_update_object(eval_ctx, scene, view_layer, ob, 0);
+ PE_update_object(eval_ctx, scene, ob, 0);
}
static int disconnect_hair_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= ED_object_context(C);
ParticleSystem *psys= NULL;
const bool all = RNA_boolean_get(op->ptr, "all");
@@ -635,12 +611,12 @@ static int disconnect_hair_exec(bContext *C, wmOperator *op)
if (all) {
for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- disconnect_hair(&eval_ctx, scene, view_layer, ob, psys);
+ disconnect_hair(&eval_ctx, scene, ob, psys);
}
}
else {
psys = psys_get_current(ob);
- disconnect_hair(&eval_ctx, scene, view_layer, ob, psys);
+ disconnect_hair(&eval_ctx, scene, ob, psys);
}
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -667,7 +643,7 @@ void PARTICLE_OT_disconnect_hair(wmOperatorType *ot)
* from/to_mat : additional transform for from/to particles (e.g. for using object space copying)
*/
static bool remap_hair_emitter(
- const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, Object *ob, ParticleSystem *psys,
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ParticleSystem *psys,
Object *target_ob, ParticleSystem *target_psys, PTCacheEdit *target_edit,
float from_mat[4][4], float to_mat[4][4], bool from_global, bool to_global)
{
@@ -853,13 +829,13 @@ static bool remap_hair_emitter(
psys_free_path_cache(target_psys, target_edit);
- PE_update_object(eval_ctx, scene, view_layer, target_ob, 0);
+ PE_update_object(eval_ctx, scene, target_ob, 0);
return true;
}
static bool connect_hair(
- const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ const EvaluationContext *eval_ctx, Scene *scene,
Object *ob, ParticleSystem *psys)
{
bool ok;
@@ -868,7 +844,7 @@ static bool connect_hair(
return false;
ok = remap_hair_emitter(
- eval_ctx, scene, view_layer, ob, psys, ob, psys, psys->edit,
+ eval_ctx, scene, ob, psys, ob, psys, psys->edit,
ob->obmat, ob->obmat, psys->flag & PSYS_GLOBAL_HAIR, false);
psys->flag &= ~PSYS_GLOBAL_HAIR;
@@ -879,7 +855,6 @@ static int connect_hair_exec(bContext *C, wmOperator *op)
{
EvaluationContext eval_ctx;
Scene *scene= CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= ED_object_context(C);
ParticleSystem *psys= NULL;
const bool all = RNA_boolean_get(op->ptr, "all");
@@ -892,12 +867,12 @@ static int connect_hair_exec(bContext *C, wmOperator *op)
if (all) {
for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- any_connected |= connect_hair(&eval_ctx, scene, view_layer, ob, psys);
+ any_connected |= connect_hair(&eval_ctx, scene, ob, psys);
}
}
else {
psys = psys_get_current(ob);
- any_connected |= connect_hair(&eval_ctx, scene, view_layer, ob, psys);
+ any_connected |= connect_hair(&eval_ctx, scene, ob, psys);
}
if (!any_connected) {
@@ -934,7 +909,7 @@ typedef enum eCopyParticlesSpace {
} eCopyParticlesSpace;
static void copy_particle_edit(
- const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ const EvaluationContext *eval_ctx, Scene *scene,
Object *ob, ParticleSystem *psys, ParticleSystem *psys_from)
{
PTCacheEdit *edit_from = psys_from->edit, *edit;
@@ -954,10 +929,7 @@ static void copy_particle_edit(
edit->emitter_field = NULL;
edit->emitter_cosnos = NULL;
-
- BLI_listbase_clear(&edit->undo);
- edit->curundo = NULL;
-
+
edit->points = MEM_dupallocN(edit_from->points);
pa = psys->particles;
LOOP_POINTS {
@@ -985,10 +957,7 @@ static void copy_particle_edit(
recalc_lengths(edit);
recalc_emitter_field(ob, psys);
- PE_update_object(eval_ctx, scene, view_layer, ob, true);
-
- PTCacheUndo_clear(edit);
- PE_undo_push(scene, view_layer, "Original");
+ PE_update_object(eval_ctx, scene, ob, true);
}
static void remove_particle_systems_from_object(Object *ob_to)
@@ -1018,7 +987,6 @@ static void remove_particle_systems_from_object(Object *ob_to)
/* single_psys_from is optional, if NULL all psys of ob_from are copied */
static bool copy_particle_systems_to_object(const bContext *C,
Scene *scene,
- ViewLayer *view_layer,
Object *ob_from,
ParticleSystem *single_psys_from,
Object *ob_to,
@@ -1103,7 +1071,7 @@ static bool copy_particle_systems_to_object(const bContext *C,
DM_ensure_tessface(psmd->dm_final);
if (psys_from->edit) {
- copy_particle_edit(&eval_ctx, scene, view_layer, ob_to, psys, psys_from);
+ copy_particle_edit(&eval_ctx, scene, ob_to, psys, psys_from);
}
if (duplicate_settings) {
@@ -1139,7 +1107,7 @@ static bool copy_particle_systems_to_object(const bContext *C,
}
if (ob_from != ob_to) {
remap_hair_emitter(
- &eval_ctx, scene, view_layer, ob_from, psys_from, ob_to, psys, psys->edit,
+ &eval_ctx, scene, ob_from, psys_from, ob_to, psys, psys->edit,
from_mat, to_mat, psys_from->flag & PSYS_GLOBAL_HAIR, psys->flag & PSYS_GLOBAL_HAIR);
}
@@ -1174,7 +1142,6 @@ static int copy_particle_systems_exec(bContext *C, wmOperator *op)
const bool remove_target_particles = RNA_boolean_get(op->ptr, "remove_target_particles");
const bool use_active = RNA_boolean_get(op->ptr, "use_active");
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob_from = ED_object_active_context(C);
ParticleSystem *psys_from = use_active ? CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data : NULL;
@@ -1189,7 +1156,7 @@ static int copy_particle_systems_exec(bContext *C, wmOperator *op)
remove_particle_systems_from_object(ob_to);
changed = true;
}
- if (copy_particle_systems_to_object(C, scene, view_layer, ob_from, psys_from, ob_to, space, false))
+ if (copy_particle_systems_to_object(C, scene, ob_from, psys_from, ob_to, space, false))
changed = true;
else
fail++;
@@ -1250,7 +1217,7 @@ static int duplicate_particle_systems_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data;
- copy_particle_systems_to_object(C, scene, CTX_data_view_layer(C), ob, psys, ob,
+ copy_particle_systems_to_object(C, scene, ob, psys, ob,
PAR_COPY_SPACE_OBJECT, duplicate_settings);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index 12e01228e1e..c0b2ae8ded4 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -39,7 +39,7 @@
/* types */
#include "DNA_action_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_fluidsim.h"
+#include "DNA_object_fluidsim_types.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
@@ -48,8 +48,6 @@
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_fluidsim.h"
-#include "BKE_global.h"
-#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_report.h"
@@ -69,6 +67,8 @@
/* enable/disable overall compilation */
#ifdef WITH_MOD_FLUID
+#include "BKE_global.h"
+
#include "WM_api.h"
#include "DNA_scene_types.h"
@@ -409,7 +409,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid
/* Modifying the global scene isn't nice, but we can do it in
* this part of the process before a threaded job is created */
scene->r.cfra = (int)eval_time;
- ED_update_for_newframe(CTX_data_main(C), scene, view_layer, depsgraph);
+ ED_update_for_newframe(CTX_data_main(C), depsgraph);
/* now scene data should be current according to animation system, so we fill the channels */
@@ -959,7 +959,7 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
/* reset to original current frame */
scene->r.cfra = origFrame;
- ED_update_for_newframe(CTX_data_main(C), scene, view_layer, depsgraph);
+ ED_update_for_newframe(CTX_data_main(C), depsgraph);
/* ******** init domain object's matrix ******** */
copy_m4_m4(domainMat, fsDomain->obmat);
diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h
index 6b6df15e987..246bf79360f 100644
--- a/source/blender/editors/physics/physics_intern.h
+++ b/source/blender/editors/physics/physics_intern.h
@@ -33,6 +33,13 @@
#ifndef __PHYSICS_INTERN_H__
#define __PHYSICS_INTERN_H__
+struct EvaluationContext;
+struct Object;
+struct PTCacheEdit;
+struct ParticleSystem;
+struct PointCache;
+struct Scene;
+struct ViewLayer;
struct wmOperatorType;
/* particle_edit.c */
@@ -63,6 +70,13 @@ void PARTICLE_OT_edited_clear(struct wmOperatorType *ot);
void PARTICLE_OT_unify_length(struct wmOperatorType *ot);
+void PE_create_particle_edit(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, struct PointCache *cache, struct ParticleSystem *psys);
+void recalc_lengths(struct PTCacheEdit *edit);
+void recalc_emitter_field(struct Object *ob, struct ParticleSystem *psys);
+void update_world_cos(struct Object *ob, struct PTCacheEdit *edit);
+
/* particle_object.c */
void OBJECT_OT_particle_system_add(struct wmOperatorType *ot);
void OBJECT_OT_particle_system_remove(struct wmOperatorType *ot);
diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c
index a859f664dc8..fdafd6c28ed 100644
--- a/source/blender/editors/physics/physics_pointcache.c
+++ b/source/blender/editors/physics/physics_pointcache.c
@@ -177,18 +177,7 @@ static PTCacheBaker *ptcache_baker_create(bContext *C, wmOperator *op, bool all)
PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
Object *ob = ptr.id.data;
PointCache *cache = ptr.data;
-
- ListBase pidlist;
- BKE_ptcache_ids_from_object(&pidlist, ob, baker->scene, MAX_DUPLI_RECUR);
-
- for (PTCacheID *pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache) {
- baker->pid = *pid;
- break;
- }
- }
-
- BLI_freelistN(&pidlist);
+ baker->pid = BKE_ptcache_id_find(ob, baker->scene, cache);
}
return baker;
@@ -260,7 +249,7 @@ static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op))
PTCacheID *pid;
ListBase pidlist;
- FOREACH_SCENE_OBJECT(scene, ob)
+ FOREACH_SCENE_OBJECT_BEGIN(scene, ob)
{
BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
@@ -272,7 +261,7 @@ static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op))
WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
@@ -391,22 +380,14 @@ static int ptcache_add_new_exec(bContext *C, wmOperator *UNUSED(op))
PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
Object *ob= ptr.id.data;
PointCache *cache= ptr.data;
- PTCacheID *pid;
- ListBase pidlist;
+ PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
- BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
-
- for (pid=pidlist.first; pid; pid=pid->next) {
- if (pid->cache == cache) {
- PointCache *cache_new = BKE_ptcache_add(pid->ptcaches);
- cache_new->step = pid->default_step;
- *(pid->cache_ptr) = cache_new;
- break;
- }
+ if (pid.cache) {
+ PointCache *cache_new = BKE_ptcache_add(pid.ptcaches);
+ cache_new->step = pid.default_step;
+ *(pid.cache_ptr) = cache_new;
}
- BLI_freelistN(&pidlist);
-
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
@@ -418,26 +399,15 @@ static int ptcache_remove_exec(bContext *C, wmOperator *UNUSED(op))
Scene *scene= CTX_data_scene(C);
Object *ob= ptr.id.data;
PointCache *cache= ptr.data;
- PTCacheID *pid;
- ListBase pidlist;
-
- BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
-
- for (pid=pidlist.first; pid; pid=pid->next) {
- if (pid->cache == cache) {
- if (pid->ptcaches->first == pid->ptcaches->last)
- continue; /* don't delete last cache */
-
- BLI_remlink(pid->ptcaches, pid->cache);
- BKE_ptcache_free(pid->cache);
- *(pid->cache_ptr) = pid->ptcaches->first;
+ PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
- break;
- }
+ /* don't delete last cache */
+ if (pid.cache && pid.ptcaches->first != pid.ptcaches->last) {
+ BLI_remlink(pid.ptcaches, pid.cache);
+ BKE_ptcache_free(pid.cache);
+ *(pid.cache_ptr) = pid.ptcaches->first;
}
- BLI_freelistN(&pidlist);
-
WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index f77e164ba16..3bcc047bf5b 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -38,7 +38,6 @@
#include "DNA_scene_types.h"
#include "BKE_context.h"
-#include "BKE_global.h"
#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index 3b667520550..3553ffa5033 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -43,7 +43,6 @@
#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_global.h"
#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 80bdeaa8069..51a75e36044 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -65,6 +65,7 @@
#include "BKE_sequencer.h"
#include "BKE_screen.h"
#include "BKE_scene.h"
+#include "BKE_undo_system.h"
#include "BKE_workspace.h"
#include "DEG_depsgraph.h"
@@ -76,6 +77,7 @@
#include "ED_render.h"
#include "ED_screen.h"
#include "ED_util.h"
+#include "ED_undo.h"
#include "ED_view3d.h"
#include "RE_pipeline.h"
@@ -92,6 +94,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "BLO_undofile.h"
#include "render_intern.h"
@@ -295,8 +298,8 @@ static void screen_render_view_layer_set(wmOperator *op, Main *mainp, Scene **sc
static int screen_render_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
+ RenderEngineType *re_type = RE_engines_find(scene->view_render.engine_id);
ViewLayer *view_layer = NULL;
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
Render *re;
Image *ima;
View3D *v3d = CTX_wm_view3d(C);
@@ -306,6 +309,11 @@ static int screen_render_exec(bContext *C, wmOperator *op)
const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
+ /* Cannot do render if there is not this function. */
+ if (re_type->render_to_image == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
/* custom scene and single layer re-render */
screen_render_view_layer_set(op, mainp, &scene, &view_layer);
@@ -315,7 +323,6 @@ static int screen_render_exec(bContext *C, wmOperator *op)
}
re = RE_NewSceneRender(scene);
- RE_SetDepsgraph(re, CTX_data_depsgraph(C));
lay_override = (v3d && v3d->lay != scene->lay) ? v3d->lay : 0;
G.is_break = false;
@@ -333,17 +340,17 @@ static int screen_render_exec(bContext *C, wmOperator *op)
RE_SetReports(re, op->reports);
- BLI_begin_threaded_malloc();
+ BLI_threaded_malloc_begin();
if (is_animation)
RE_BlenderAnim(re, mainp, scene, camera_override, lay_override, scene->r.sfra, scene->r.efra, scene->r.frame_step);
else
RE_BlenderFrame(re, mainp, scene, view_layer, camera_override, lay_override, scene->r.cfra, is_write_still);
- BLI_end_threaded_malloc();
+ BLI_threaded_malloc_end();
RE_SetReports(re, NULL);
// no redraw needed, we leave state as we entered it
- ED_update_for_newframe(mainp, scene, view_layer, depsgraph);
+ ED_update_for_newframe(mainp, CTX_data_depsgraph(C));
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
@@ -532,10 +539,8 @@ static void render_image_update_pass_and_layer(RenderJob *rj, RenderResult *rr,
int layer = BLI_findstringindex(&main_rr->layers,
(char *)rr->renlay->name,
offsetof(RenderLayer, name));
- if (layer != rj->last_layer) {
- sima->iuser.layer = layer;
- rj->last_layer = layer;
- }
+ sima->iuser.layer = layer;
+ rj->last_layer = layer;
}
iuser->pass = sima->iuser.pass;
@@ -633,7 +638,21 @@ static void render_image_restore_layer(RenderJob *rj)
if (sa == rj->sa) {
if (sa->spacetype == SPACE_IMAGE) {
SpaceImage *sima = sa->spacedata.first;
- sima->iuser.layer = rj->orig_layer;
+
+ if (RE_HasSingleLayer(rj->re)) {
+ /* For single layer renders keep the active layer
+ * visible, or show the compositing result. */
+ RenderResult *rr = RE_AcquireResultRead(rj->re);
+ if (RE_HasCombinedLayer(rr)) {
+ sima->iuser.layer = 0;
+ }
+ RE_ReleaseResult(rj->re);
+ }
+ else {
+ /* For multiple layer render, set back the layer
+ * that was set at the start of rendering. */
+ sima->iuser.layer = rj->orig_layer;
+ }
}
return;
}
@@ -657,7 +676,7 @@ static void render_endjob(void *rjv)
if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) {
/* possible this fails of loading new file while rendering */
if (G.main->wm.first) {
- ED_update_for_newframe(G.main, rj->scene, rj->view_layer, rj->depsgraph);
+ ED_update_for_newframe(G.main, rj->depsgraph);
}
}
@@ -844,6 +863,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
Main *mainp;
ViewLayer *view_layer = NULL;
Scene *scene = CTX_data_scene(C);
+ RenderEngineType *re_type = RE_engines_find(scene->view_render.engine_id);
Render *re;
wmJob *wm_job;
RenderJob *rj;
@@ -856,7 +876,12 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
const char *name;
ScrArea *sa;
-
+
+ /* Cannot do render if there is not this function. */
+ if (re_type->render_to_image == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
/* only one render job at a time */
if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER))
return OPERATOR_CANCELLED;
@@ -879,7 +904,8 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
/* get main */
if (G.debug_value == 101) {
/* thread-safety experiment, copy main from the undo buffer */
- mainp = BKE_undo_get_main(&scene);
+ struct MemFile *memfile = ED_undosys_stack_memfile_get_active(CTX_wm_manager(C)->undo_stack);
+ mainp = BLO_memfile_main_get(memfile, CTX_data_main(C), &scene);
}
else
mainp = CTX_data_main(C);
@@ -996,7 +1022,6 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
RE_current_scene_update_cb(re, rj, current_scene_update);
RE_stats_draw_cb(re, rj, image_renderinfo_cb);
RE_progress_cb(re, rj, render_progress_update);
- RE_SetDepsgraph(re, CTX_data_depsgraph(C));
rj->re = re;
G.is_break = false;
@@ -1067,6 +1092,7 @@ typedef struct RenderPreview {
wmJob *job;
Scene *scene;
+ EvaluationContext *eval_ctx;
Depsgraph *depsgraph;
ScrArea *sa;
ARegion *ar;
@@ -1315,7 +1341,7 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda
WM_job_main_thread_lock_release(rp->job);
/* do preprocessing like building raytree, shadows, volumes, SSS */
- RE_Database_Preprocess(re);
+ RE_Database_Preprocess(rp->eval_ctx, re);
/* conversion not completed, need to do it again */
if (!rstats->convertdone) {
@@ -1381,6 +1407,7 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda
static void render_view3d_free(void *customdata)
{
RenderPreview *rp = customdata;
+ DEG_evaluation_context_free(rp->eval_ctx);
MEM_freeN(rp);
}
@@ -1423,8 +1450,10 @@ static bool render_view3d_flag_changed(RenderEngine *engine, const bContext *C)
job_update_flag |= PR_UPDATE_DATABASE;
/* load editmesh */
- if (scene->obedit)
- ED_object_editmode_load(scene->obedit);
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit) {
+ ED_object_editmode_load(obedit);
+ }
}
engine->update_flag = 0;
@@ -1494,6 +1523,8 @@ static void render_view3d_do(RenderEngine *engine, const bContext *C)
/* customdata for preview thread */
rp->scene = scene;
rp->depsgraph = depsgraph;
+ rp->eval_ctx = DEG_evaluation_context_new(DAG_EVAL_PREVIEW);
+ CTX_data_eval_ctx(C, rp->eval_ctx);
rp->engine = engine;
rp->sa = CTX_wm_area(C);
rp->ar = CTX_wm_region(C);
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 6e969067985..be2b184626d 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -57,6 +57,8 @@
#include "DEG_depsgraph.h"
+#include "DRW_engine.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -72,7 +74,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "GPU_compositing.h"
#include "GPU_framebuffer.h"
#include "GPU_glew.h"
#include "GPU_matrix.h"
@@ -120,7 +121,6 @@ typedef struct OGLRender {
GPUOffScreen *ofs;
int ofs_samples;
bool ofs_full_samples;
- GPUFX *fx;
int sizex, sizey;
int write_still;
@@ -323,6 +323,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
unsigned char *gp_rect;
unsigned char *render_rect = (unsigned char *)RE_RenderViewGetById(rr, oglrender->view_id)->rect32;
+ DRW_opengl_context_enable();
GPU_offscreen_bind(oglrender->ofs, true);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@@ -342,6 +343,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
blend_color_mix_byte(&render_rect[i], &render_rect[i], &gp_rect[i]);
}
GPU_offscreen_unbind(oglrender->ofs, true);
+ DRW_opengl_context_disable();
MEM_freeN(gp_rect);
}
@@ -351,6 +353,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
char err_out[256] = "unknown";
ImBuf *ibuf_view;
const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL;
+ struct RenderEngineType *engine_type = CTX_data_engine_type(C);
unsigned int draw_flags = V3D_OFSDRAW_NONE;
draw_flags |= (oglrender->ofs_full_samples) ? V3D_OFSDRAW_USE_FULL_SAMPLE : 0;
@@ -359,9 +362,10 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
draw_flags |= (draw_bgpic) ? V3D_OFSDRAW_USE_BACKGROUND : 0;
ibuf_view = ED_view3d_draw_offscreen_imbuf(
- &eval_ctx, scene, view_layer, v3d, ar, sizex, sizey,
+ &eval_ctx, scene, view_layer, engine_type,
+ v3d, ar, sizex, sizey,
IB_rectfloat, draw_flags, alpha_mode, oglrender->ofs_samples, viewname,
- oglrender->fx, oglrender->ofs, err_out);
+ oglrender->ofs, err_out);
/* for stamp only */
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
@@ -371,10 +375,11 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
else {
draw_flags |= (V3D_OFSDRAW_USE_GPENCIL | V3D_OFSDRAW_USE_BACKGROUND);
ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(
- &eval_ctx, scene, view_layer, scene->camera, oglrender->sizex, oglrender->sizey,
+ &eval_ctx, scene, view_layer, engine_type,
+ scene->camera, oglrender->sizex, oglrender->sizey,
IB_rectfloat, draw_flags, OB_SOLID,
alpha_mode, oglrender->ofs_samples, viewname,
- oglrender->fx, oglrender->ofs, err_out);
+ oglrender->ofs, err_out);
camera = scene->camera;
}
@@ -541,7 +546,6 @@ static void screen_opengl_render_apply(const bContext *C, OGLRender *oglrender)
for (view_id = 0; view_id < oglrender->views_len; view_id++) {
context.view_id = view_id;
context.gpu_offscreen = oglrender->ofs;
- context.gpu_fx = oglrender->fx;
context.gpu_full_samples = oglrender->ofs_full_samples;
oglrender->seq_data.ibufs_arr[view_id] = BKE_sequencer_give_ibuf(&context, CFRA, chanshown);
@@ -652,7 +656,9 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
sizey = (scene->r.size * scene->r.ysch) / 100;
/* corrects render size with actual size, not every card supports non-power-of-two dimensions */
- ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, true, err_out);
+ DRW_opengl_context_enable(); /* Offscreen creation needs to be done in DRW context. */
+ ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, true, true, err_out);
+ DRW_opengl_context_disable();
if (!ofs) {
BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out);
@@ -700,19 +706,6 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
/* apply immediately in case we're rendering from a script,
* running notifiers again will overwrite */
oglrender->scene->customdata_mask |= oglrender->scene->customdata_mask_modal;
-
- if (oglrender->v3d->fx_settings.fx_flag & (GPU_FX_FLAG_DOF | GPU_FX_FLAG_SSAO)) {
- oglrender->fx = GPU_fx_compositor_create();
- }
- }
- else if (is_sequencer) {
- /* NOTE: We allow animation of DoF setting for flexibility in edits, so
- * we can't check in advance whether we need FX compositor or not.
- * We just always allocated it and make sure it doesn't add extra
- * overhead rather than memory allocation here if it's not really
- * needed.
- */
- oglrender->fx = GPU_fx_compositor_create();
}
/* create render */
@@ -827,9 +820,8 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
if (oglrender->timer) { /* exec will not have a timer */
Depsgraph *depsgraph = oglrender->depsgraph;
- ViewLayer *view_layer = oglrender->view_layer;
scene->r.cfra = oglrender->cfrao;
- BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
WM_event_remove_timer(oglrender->wm, oglrender->win, oglrender->timer);
}
@@ -838,10 +830,9 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene);
- if (oglrender->fx)
- GPU_fx_compositor_destroy(oglrender->fx);
-
+ DRW_opengl_context_enable();
GPU_offscreen_free(oglrender->ofs);
+ DRW_opengl_context_disable();
if (oglrender->is_sequencer) {
MEM_freeN(oglrender->seq_data.ibufs_arr);
@@ -1029,7 +1020,6 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
OGLRender *oglrender = op->customdata;
Scene *scene = oglrender->scene;
- ViewLayer *view_layer = oglrender->view_layer;
Depsgraph *depsgraph = oglrender->depsgraph;
char name[FILE_MAX];
bool ok = false;
@@ -1041,7 +1031,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
if (CFRA < oglrender->nfra)
CFRA++;
while (CFRA < oglrender->nfra) {
- BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
CFRA++;
}
@@ -1063,7 +1053,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
WM_cursor_time(oglrender->win, scene->r.cfra);
- BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
if (view_context) {
if (oglrender->rv3d->persp == RV3D_CAMOB && oglrender->v3d->camera && oglrender->v3d->scenelock) {
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 2e3091268a9..4297d4fa316 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -455,9 +455,18 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
}
else {
/* use current scene world to light sphere */
- if (mat->pr_type == MA_SPHERE_A) {
+ if (mat->pr_type == MA_SPHERE_A && sp->pr_method == PR_BUTS_RENDER) {
+ /* Use current scene world to light sphere. */
sce->world = preview_get_localized_world(sp, scene->world);
}
+ else if (sce->world) {
+ /* Use a default world color. Using the current
+ * scene world can be slow if it has big textures. */
+ sce->world->use_nodes = false;
+ sce->world->horr = 0.5f;
+ sce->world->horg = 0.5f;
+ sce->world->horb = 0.5f;
+ }
}
if (sp->pr_method == PR_ICON_RENDER) {
@@ -466,10 +475,6 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
}
else {
set_preview_layer(view_layer, MA_SPHERE_A);
-
- /* same as above, use current scene world to light sphere */
- if (BKE_scene_use_new_shading_nodes(scene))
- sce->world = preview_get_localized_world(sp, scene->world);
}
}
else {
@@ -569,6 +574,14 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
}
else {
set_preview_layer(view_layer, MA_LAMP);
+
+ if (sce->world) {
+ /* Only use lighting from the lamp. */
+ sce->world->use_nodes = false;
+ sce->world->horr = 0.0f;
+ sce->world->horg = 0.0f;
+ sce->world->horb = 0.0f;
+ }
}
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
@@ -607,7 +620,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
/* TODO(sergey): Use proper flag for tagging here. */
DEG_graph_id_tag_update(pr_main, depsgraph, &sce->id, 0);
DEG_relations_tag_update(pr_main);
- BKE_scene_graph_update_tagged(pr_main->eval_ctx, depsgraph, pr_main, sce, view_layer);
+ BKE_scene_graph_update_tagged(depsgraph, pr_main);
return sce;
}
@@ -1363,7 +1376,7 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
sp->bmain = CTX_data_main(C);
sp->view_render = view_render;
- /* hardcoded preview .blend for cycles/internal, this should be solved
+ /* hardcoded preview .blend for Eevee + cycles/internal, this should be solved
* once with custom preview .blend path for external engines */
if ((method != PR_NODE_RENDER) && id_type != ID_TE && use_new_shading) {
sp->pr_main = G_pr_main_cycles;
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index eebe69b7a19..d29985041c6 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -202,7 +202,7 @@ void ED_render_engine_changed(Main *bmain)
update_ctx.bmain = bmain;
for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
update_ctx.scene = scene;
- BLI_LISTBASE_FOREACH(ViewLayer *, view_layer, &scene->view_layers) {
+ LISTBASE_FOREACH(ViewLayer *, view_layer, &scene->view_layers) {
/* TDODO(sergey): Iterate over depsgraphs instead? */
update_ctx.depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
update_ctx.view_layer = view_layer;
@@ -542,8 +542,6 @@ void ED_render_id_flush_update(const DEGEditorUpdateContext *update_ctx, ID *id)
return;
}
Main *bmain = update_ctx->bmain;
- Scene *scene = update_ctx->scene;
- ViewLayer *view_layer = update_ctx->view_layer;
/* Internal ID update handlers. */
switch (GS(id->name)) {
case ID_MA:
@@ -570,42 +568,6 @@ void ED_render_id_flush_update(const DEGEditorUpdateContext *update_ctx, ID *id)
render_engine_flag_changed(bmain, RE_ENGINE_UPDATE_OTHER);
break;
}
- /* Inform all draw managers about changes.
- *
- * TODO(sergey): This code is run for every updated ID, via flushing
- * mechanism. How can we avoid iterating over the whole interface for
- * every of those IDs? One of the ideas would be to call draw manager's
- * ID update which is not bound to any of contexts.
- */
- {
- wmWindowManager *wm = bmain->wm.first;
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
- bScreen *sc = WM_window_get_active_screen(win);
- WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
- ViewRender *view_render = BKE_viewrender_get(win->scene, workspace);
- for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype != SPACE_VIEW3D) {
- continue;
- }
- for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype != RGN_TYPE_WINDOW) {
- continue;
- }
- RenderEngineType *engine_type = RE_engines_find(view_render->engine_id);
- DRW_notify_id_update(
- (&(DRWUpdateContext){
- .bmain = bmain,
- .scene = scene,
- .view_layer = view_layer,
- .ar = ar,
- .v3d = (View3D *)sa->spacedata.first,
- .engine_type = engine_type
- }),
- id);
- }
- }
- }
- }
}
diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c
index 812f9a736bf..d16d60ba7b9 100644
--- a/source/blender/editors/scene/scene_edit.c
+++ b/source/blender/editors/scene/scene_edit.c
@@ -42,6 +42,7 @@
#include "BLT_translation.h"
+#include "DNA_object_types.h"
#include "DNA_workspace_types.h"
#include "ED_object.h"
@@ -113,32 +114,42 @@ bool ED_scene_delete(bContext *C, Main *bmain, wmWindow *win, Scene *scene)
return true;
}
-void ED_scene_exit(bContext *C)
-{
- ED_object_editmode_exit(C, EM_FREEDATA | EM_DO_UNDO);
-}
-
static ViewLayer *scene_change_get_new_view_layer(const WorkSpace *workspace, const Scene *scene_new)
{
ViewLayer *layer_new = BKE_workspace_view_layer_get(workspace, scene_new);
return layer_new ? layer_new : BKE_view_layer_from_scene_get(scene_new);
}
-void ED_scene_changed_update(Main *bmain, bContext *C, Scene *scene_new, const bScreen *active_screen)
+void ED_scene_change_update(
+ Main *bmain, bContext *C,
+ wmWindow *win, const bScreen *screen, Scene *UNUSED(scene_old), Scene *scene_new)
{
WorkSpace *workspace = CTX_wm_workspace(C);
ViewLayer *layer_new = scene_change_get_new_view_layer(workspace, scene_new);
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene_new, layer_new, true);
-
+ Object *obact_new = OBACT(layer_new);
+ UNUSED_VARS(obact_new);
+
+#if 0
+ /* mode syncing */
+ EvaluationContext eval_ctx_old;
+ CTX_data_eval_ctx(C, &eval_ctx_old);
+ eObjectMode object_mode_old = workspace->object_mode;
+ ViewLayer *layer_old = BKE_view_layer_from_workspace_get(scene_old, workspace);
+ Object *obact_old = OBACT(layer_old);
+ UNUSED_VARS(obact_old, object_mode_old);
+#endif
+
+ win->scene = scene_new;
CTX_data_scene_set(C, scene_new);
BKE_workspace_view_layer_set(workspace, layer_new, scene_new);
BKE_scene_set_background(bmain, scene_new);
DEG_graph_relations_update(depsgraph, bmain, scene_new, layer_new);
DEG_on_visible_update(bmain, false);
- ED_screen_update_after_scene_change(active_screen, scene_new, layer_new);
+ ED_screen_update_after_scene_change(screen, scene_new, layer_new);
ED_render_engine_changed(bmain);
- ED_update_for_newframe(bmain, scene_new, layer_new, depsgraph);
+ ED_update_for_newframe(bmain, depsgraph);
/* complete redraw */
WM_event_add_notifier(C, NC_WINDOW, NULL);
@@ -186,13 +197,15 @@ bool ED_scene_view_layer_delete(
return false;
}
+ /* We need to unset nodetrees before removing the layer, otherwise its index will be -1. */
+ view_layer_remove_unset_nodetrees(bmain, scene, layer);
+
BLI_remlink(&scene->view_layers, layer);
BLI_assert(BLI_listbase_is_empty(&scene->view_layers) == false);
scene->active_view_layer = 0;
ED_workspace_view_layer_unset(bmain, scene, layer, scene->view_layers.first);
BKE_workspace_view_layer_remove_references(bmain, layer);
- view_layer_remove_unset_nodetrees(bmain, scene, layer);
BKE_view_layer_free(layer);
diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt
index 02584a4611b..29b9971eabb 100644
--- a/source/blender/editors/screen/CMakeLists.txt
+++ b/source/blender/editors/screen/CMakeLists.txt
@@ -26,6 +26,7 @@ set(INC
../../blenloader
../../blentranslation
../../bmesh
+ ../../depsgraph
../../gpu
../../imbuf
../../makesdna
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 274dbcc73cb..105fff38f62 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -41,10 +41,10 @@
#include "BLI_utildefines.h"
#include "BLI_linklist_stack.h"
-
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_screen.h"
+#include "BKE_workspace.h"
#include "RNA_access.h"
#include "RNA_types.h"
@@ -52,7 +52,6 @@
#include "WM_api.h"
#include "WM_types.h"
#include "WM_message.h"
-#include "wm_subwindow.h"
#include "ED_screen.h"
#include "ED_screen_types.h"
@@ -67,6 +66,7 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "IMB_metadata.h"
#include "UI_interface.h"
#include "UI_interface_icons.h"
@@ -91,7 +91,7 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct)
/* set transp line */
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -103,9 +103,11 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct)
/* right */
immAttrib4ub(color, 0, 0, 0, 30);
immVertex2f(pos, rect.xmax, rect.ymax);
+ immAttrib4ub(color, 0, 0, 0, 30);
immVertex2f(pos, rect.xmax, rect.ymin);
/* bottom */
+ immAttrib4ub(color, 0, 0, 0, 30);
immVertex2f(pos, rect.xmin, rect.ymin);
/* left */
@@ -113,6 +115,7 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct)
immVertex2f(pos, rect.xmin, rect.ymax);
/* top */
+ immAttrib4ub(color, 255, 255, 255, 30);
immVertex2f(pos, rect.xmax, rect.ymax);
immEnd();
@@ -265,26 +268,32 @@ static void area_draw_azone(short x1, short y1, short x2, short y2)
immAttrib4ub(col, 255, 255, 255, 180);
immVertex2f(pos, x1, y2);
+ immAttrib4ub(col, 255, 255, 255, 180);
immVertex2f(pos, x2, y1);
immAttrib4ub(col, 255, 255, 255, 130);
immVertex2f(pos, x1, y2 - dy);
+ immAttrib4ub(col, 255, 255, 255, 130);
immVertex2f(pos, x2 - dx, y1);
immAttrib4ub(col, 255, 255, 255, 80);
immVertex2f(pos, x1, y2 - 2 * dy);
+ immAttrib4ub(col, 255, 255, 255, 80);
immVertex2f(pos, x2 - 2 * dx, y1);
immAttrib4ub(col, 0, 0, 0, 210);
immVertex2f(pos, x1, y2 + 1);
+ immAttrib4ub(col, 0, 0, 0, 210);
immVertex2f(pos, x2 + 1, y1);
immAttrib4ub(col, 0, 0, 0, 180);
immVertex2f(pos, x1, y2 - dy + 1);
+ immAttrib4ub(col, 0, 0, 0, 180);
immVertex2f(pos, x2 - dx + 1, y1);
immAttrib4ub(col, 0, 0, 0, 150);
immVertex2f(pos, x1, y2 - 2 * dy + 1);
+ immAttrib4ub(col, 0, 0, 0, 150);
immVertex2f(pos, x2 - 2 * dx + 1, y1);
immEnd();
@@ -450,7 +459,7 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar)
glLineWidth(1.0f);
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
gpuPushMatrix();
gpuTranslate2f(-ar->winrct.xmin, -ar->winrct.ymin);
@@ -495,23 +504,6 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar)
glDisable(GL_BLEND);
}
-/* only exported for WM */
-/* makes region ready for drawing, sets pixelspace */
-void ED_region_set(const bContext *C, ARegion *ar)
-{
- wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = CTX_wm_area(C);
-
- ar->drawrct = ar->winrct;
-
- /* note; this sets state, so we can use wmOrtho and friends */
- wmSubWindowScissorSet(win, ar->swinid, &ar->drawrct, true);
-
- UI_SetTheme(sa ? sa->spacetype : 0, ar->type ? ar->type->regionid : 0);
-
- ED_region_pixelspace(ar);
-}
-
/* Follow wmMsgNotifyFn spec */
void ED_region_do_msg_notify_tag_redraw(
bContext *UNUSED(C), wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
@@ -546,27 +538,15 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = CTX_wm_area(C);
ARegionType *at = ar->type;
- bool scissor_pad;
/* see BKE_spacedata_draw_locks() */
if (at->do_lock)
return;
- /* if no partial draw rect set, full rect */
- if (ar->drawrct.xmin == ar->drawrct.xmax) {
- ar->drawrct = ar->winrct;
- scissor_pad = true;
- }
- else {
- /* extra clip for safety */
- BLI_rcti_isect(&ar->winrct, &ar->drawrct, &ar->drawrct);
- scissor_pad = false;
- }
-
ar->do_draw |= RGN_DRAWING;
- /* note; this sets state, so we can use wmOrtho and friends */
- wmSubWindowScissorSet(win, ar->swinid, &ar->drawrct, scissor_pad);
+ /* Set viewport, scissor, ortho and ar->drawrct. */
+ wmPartialViewport(&ar->drawrct, &ar->winrct, &ar->drawrct);
wmOrtho2_region_pixelspace(ar);
@@ -1453,24 +1433,14 @@ static void area_calc_totrct(ScrArea *sa, int sizex, int sizey)
/* used for area initialize below */
-static void region_subwindow(wmWindow *win, ARegion *ar, bool activate)
+static void region_subwindow(ARegion *ar)
{
bool hidden = (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) != 0;
if ((ar->alignment & RGN_SPLIT_PREV) && ar->prev)
hidden = hidden || (ar->prev->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL));
- if (hidden) {
- if (ar->swinid)
- wm_subwindow_close(win, ar->swinid);
- ar->swinid = 0;
- }
- else if (ar->swinid == 0) {
- ar->swinid = wm_subwindow_open(win, &ar->winrct, activate);
- }
- else {
- wm_subwindow_position(win, ar->swinid, &ar->winrct, activate);
- }
+ ar->visible = !hidden;
}
static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *handlers, int flag)
@@ -1577,9 +1547,9 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
/* region windows, default and own handlers */
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- region_subwindow(win, ar, false);
+ region_subwindow(ar);
- if (ar->swinid) {
+ if (ar->visible) {
/* default region handlers */
ed_default_handlers(wm, sa, &ar->handlers, ar->type->keymapflag);
/* own handlers */
@@ -1606,22 +1576,16 @@ static void region_update_rect(ARegion *ar)
/**
* Call to move a popup window (keep OpenGL context free!)
*/
-void ED_region_update_rect(bContext *C, ARegion *ar)
+void ED_region_update_rect(bContext *UNUSED(C), ARegion *ar)
{
- wmWindow *win = CTX_wm_window(C);
-
- wm_subwindow_rect_set(win, ar->swinid, &ar->winrct);
-
region_update_rect(ar);
}
/* externally called for floating regions like menus */
-void ED_region_init(bContext *C, ARegion *ar)
+void ED_region_init(bContext *UNUSED(C), ARegion *ar)
{
-// ARegionType *at = ar->type;
-
/* refresh can be called before window opened */
- region_subwindow(CTX_wm_window(C), ar, false);
+ region_subwindow(ar);
region_update_rect(ar);
}
@@ -1870,6 +1834,7 @@ int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco)
void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int contextnr, const bool vertical)
{
+ const WorkSpace *workspace = CTX_wm_workspace(C);
ScrArea *sa = CTX_wm_area(C);
uiStyle *style = UI_style_get_dpi();
uiBlock *block;
@@ -1920,6 +1885,11 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c
continue;
}
+ /* If we're tagged, only use compatible. */
+ if (pt->owner_id[0] && BKE_workspace_owner_id_check(workspace, pt->owner_id) == false) {
+ continue;
+ }
+
/* draw panel */
if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
BLI_SMALLSTACK_PUSH(pt_stack, pt);
@@ -2045,15 +2015,29 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c
/* before setting the view */
if (vertical) {
/* we always keep the scroll offset - so the total view gets increased with the scrolled away part */
- if (v2d->cur.ymax < - 0.001f)
- y = min_ii(y, v2d->cur.ymin);
-
+ if (v2d->cur.ymax < -FLT_EPSILON) {
+ /* Clamp to lower view boundary */
+ if (v2d->tot.ymin < -v2d->winy) {
+ y = min_ii(y, 0);
+ }
+ else {
+ y = min_ii(y, v2d->cur.ymin);
+ }
+ }
+
y = -y;
}
else {
/* don't jump back when panels close or hide */
- if (!is_context_new)
- x = max_ii(x, v2d->cur.xmax);
+ if (!is_context_new) {
+ if (v2d->tot.xmax > v2d->winx) {
+ x = max_ii(x, 0);
+ }
+ else {
+ x = max_ii(x, v2d->cur.xmax);
+ }
+ }
+
y = -y;
}
@@ -2227,7 +2211,7 @@ void ED_region_info_draw_multiline(ARegion *ar, const char *text_array[], float
BLI_rcti_size_x(&rect) + 1, BLI_rcti_size_y(&rect) + 1);
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -2280,7 +2264,7 @@ static const char *meta_data_list[] =
BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index, int offset)
{
- return (IMB_metadata_get_field(ibuf, meta_data_list[index], r_str + offset, MAX_METADATA_STR - offset) && r_str[0]);
+ return (IMB_metadata_get_field(ibuf->metadata, meta_data_list[index], r_str + offset, MAX_METADATA_STR - offset) && r_str[0]);
}
static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const bool is_top)
@@ -2543,28 +2527,34 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
float theme_color[3];
UI_GetThemeColorShade3fv(TH_BACK, (int)(20.0f * (1.0f - blendfac)), theme_color);
- immAttrib3fv(color, theme_color);
fac = 0.0f;
/* the fine resolution level */
for (int i = 0; i < count_fine; i++) {
+ immAttrib3fv(color, theme_color);
immVertex2f(pos, x1, y1 * (1.0f - fac) + y2 * fac);
+ immAttrib3fv(color, theme_color);
immVertex2f(pos, x2, y1 * (1.0f - fac) + y2 * fac);
+ immAttrib3fv(color, theme_color);
immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y1);
+ immAttrib3fv(color, theme_color);
immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y2);
fac += gridstep;
}
if (count_large > 0) {
UI_GetThemeColor3fv(TH_BACK, theme_color);
- immAttrib3fv(color, theme_color);
fac = 0.0f;
/* the large resolution level */
for (int i = 0; i < count_large; i++) {
+ immAttrib3fv(color, theme_color);
immVertex2f(pos, x1, y1 * (1.0f - fac) + y2 * fac);
+ immAttrib3fv(color, theme_color);
immVertex2f(pos, x2, y1 * (1.0f - fac) + y2 * fac);
+ immAttrib3fv(color, theme_color);
immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y1);
+ immAttrib3fv(color, theme_color);
immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y2);
fac += 4.0f * gridstep;
}
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 7ce16efdb97..cd875c73eda 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -198,6 +198,7 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state,
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &unpack_row_length);
glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w);
+ glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texid);
/* don't want nasty border artifacts */
@@ -354,142 +355,6 @@ void immDrawPixelsTex_clipping(IMMDrawPixelsTexState *state,
clip_min_x, clip_min_y, clip_max_x, clip_max_y, xzoom, yzoom, color);
}
-/* 2D Drawing Assistance */
-
-void glaDefine2DArea(rcti *screen_rect)
-{
- const int sc_w = BLI_rcti_size_x(screen_rect) + 1;
- const int sc_h = BLI_rcti_size_y(screen_rect) + 1;
-
- glViewport(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h);
- glScissor(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h);
-
- /* The GLA_PIXEL_OFS magic number is to shift the matrix so that
- * both raster and vertex integer coordinates fall at pixel
- * centers properly. For a longer discussion see the OpenGL
- * Programming Guide, Appendix H, Correctness Tips.
- */
-
- gpuOrtho2D(GLA_PIXEL_OFS, sc_w + GLA_PIXEL_OFS, GLA_PIXEL_OFS, sc_h + GLA_PIXEL_OFS);
- gpuLoadIdentity();
-}
-
-/* TODO(merwin): put the following 2D code to use, or build new 2D code inspired & informd by it */
-
-#if 0 /* UNUSED */
-
-struct gla2DDrawInfo {
- int orig_vp[4], orig_sc[4];
- float orig_projmat[16], orig_viewmat[16];
-
- rcti screen_rect;
- rctf world_rect;
-
- float wo_to_sc[2];
-};
-
-void gla2DGetMap(gla2DDrawInfo *di, rctf *rect)
-{
- *rect = di->world_rect;
-}
-
-void gla2DSetMap(gla2DDrawInfo *di, rctf *rect)
-{
- int sc_w, sc_h;
- float wo_w, wo_h;
-
- di->world_rect = *rect;
-
- sc_w = BLI_rcti_size_x(&di->screen_rect);
- sc_h = BLI_rcti_size_y(&di->screen_rect);
- wo_w = BLI_rcti_size_x(&di->world_rect);
- wo_h = BLI_rcti_size_y(&di->world_rect);
-
- di->wo_to_sc[0] = sc_w / wo_w;
- di->wo_to_sc[1] = sc_h / wo_h;
-}
-
-/** Save the current OpenGL state and initialize OpenGL for 2D
- * rendering. glaEnd2DDraw should be called on the returned structure
- * to free it and to return OpenGL to its previous state. The
- * scissor rectangle is set to match the viewport.
- *
- * See glaDefine2DArea for an explanation of why this function uses integers.
- *
- * \param screen_rect The screen rectangle to be used for 2D drawing.
- * \param world_rect The world rectangle that the 2D area represented
- * by \a screen_rect is supposed to represent. If NULL it is assumed the
- * world has a 1 to 1 mapping to the screen.
- */
-gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect)
-{
- gla2DDrawInfo *di = MEM_mallocN(sizeof(*di), "gla2DDrawInfo");
- int sc_w, sc_h;
- float wo_w, wo_h;
-
- glGetIntegerv(GL_VIEWPORT, (GLint *)di->orig_vp);
- glGetIntegerv(GL_SCISSOR_BOX, (GLint *)di->orig_sc);
- gpuGetProjectionMatrix(di->orig_projmat);
- gpuGetModelViewMatrix(di->orig_viewmat);
-
- di->screen_rect = *screen_rect;
- if (world_rect) {
- di->world_rect = *world_rect;
- }
- else {
- di->world_rect.xmin = di->screen_rect.xmin;
- di->world_rect.ymin = di->screen_rect.ymin;
- di->world_rect.xmax = di->screen_rect.xmax;
- di->world_rect.ymax = di->screen_rect.ymax;
- }
-
- sc_w = BLI_rcti_size_x(&di->screen_rect);
- sc_h = BLI_rcti_size_y(&di->screen_rect);
- wo_w = BLI_rcti_size_x(&di->world_rect);
- wo_h = BLI_rcti_size_y(&di->world_rect);
-
- di->wo_to_sc[0] = sc_w / wo_w;
- di->wo_to_sc[1] = sc_h / wo_h;
-
- glaDefine2DArea(&di->screen_rect);
-
- return di;
-}
-
-/**
- * Translate the (\a wo_x, \a wo_y) point from world coordinates into screen space.
- */
-void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *r_sc_x, int *r_sc_y)
-{
- *r_sc_x = (wo_x - di->world_rect.xmin) * di->wo_to_sc[0];
- *r_sc_y = (wo_y - di->world_rect.ymin) * di->wo_to_sc[1];
-}
-
-/**
- * Translate the \a world point from world coordinates into screen space.
- */
-void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int r_screen[2])
-{
- screen_r[0] = (world[0] - di->world_rect.xmin) * di->wo_to_sc[0];
- screen_r[1] = (world[1] - di->world_rect.ymin) * di->wo_to_sc[1];
-}
-
-/**
- * Restores the previous OpenGL state and frees the auxiliary gla data.
- */
-void glaEnd2DDraw(gla2DDrawInfo *di)
-{
- glViewport(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]);
- glScissor(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]);
- gpuLoadProjectionMatrix(di->orig_projmat);
- gpuLoadMatrix(di->orig_viewmat);
-
- MEM_freeN(di);
-}
-
-#endif /* UNUSED */
-
-
/* *************** glPolygonOffset hack ************* */
/**
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index 4c62253bef6..98a6670d10f 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -53,6 +53,8 @@
#include "BKE_sequencer.h"
#include "BKE_workspace.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "ED_armature.h"
@@ -90,8 +92,8 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
Scene *scene = WM_window_get_active_scene(win);
WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
ViewLayer *view_layer = BKE_view_layer_from_workspace_get(scene, workspace);
- Object *obedit = scene->obedit;
Object *obact = (view_layer && view_layer->basact) ? view_layer->basact->object : NULL;
+ Object *obedit = view_layer ? OBEDIT_FROM_VIEW_LAYER(view_layer) : NULL;
if (CTX_data_dir(member)) {
CTX_data_dir_set(result, screen_context_dir);
@@ -102,11 +104,11 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if (CTX_data_equals(member, "visible_objects")) {
- FOREACH_VISIBLE_OBJECT(view_layer, ob)
+ FOREACH_VISIBLE_OBJECT_BEGIN(view_layer, ob)
{
CTX_data_id_list_add(result, &ob->id);
}
- FOREACH_VISIBLE_BASE_END
+ FOREACH_VISIBLE_BASE_END;
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return 1;
}
@@ -120,43 +122,43 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if (CTX_data_equals(member, "selected_objects")) {
- FOREACH_SELECTED_OBJECT(view_layer, ob)
+ FOREACH_SELECTED_OBJECT_BEGIN(view_layer, ob)
{
CTX_data_id_list_add(result, &ob->id);
}
- FOREACH_SELECTED_OBJECT_END
+ FOREACH_SELECTED_OBJECT_END;
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return 1;
}
else if (CTX_data_equals(member, "selected_editable_objects")) {
- FOREACH_SELECTED_OBJECT(view_layer, ob)
+ FOREACH_SELECTED_OBJECT_BEGIN(view_layer, ob)
{
if (0 == BKE_object_is_libdata(ob)) {
CTX_data_id_list_add(result, &ob->id);
}
}
- FOREACH_SELECTED_OBJECT_END
+ FOREACH_SELECTED_OBJECT_END;
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return 1;
}
else if (CTX_data_equals(member, "editable_objects")) {
/* Visible + Editable, but not necessarily selected */
- FOREACH_VISIBLE_OBJECT(view_layer, ob)
+ FOREACH_VISIBLE_OBJECT_BEGIN(view_layer, ob)
{
if (0 == BKE_object_is_libdata(ob)) {
CTX_data_id_list_add(result, &ob->id);
}
}
- FOREACH_VISIBLE_OBJECT_END
+ FOREACH_VISIBLE_OBJECT_END;
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return 1;
}
else if ( CTX_data_equals(member, "visible_bases")) {
- FOREACH_VISIBLE_BASE(view_layer, base)
+ FOREACH_VISIBLE_BASE_BEGIN(view_layer, base)
{
CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
}
- FOREACH_VISIBLE_BASE_END
+ FOREACH_VISIBLE_BASE_END;
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return 1;
}
diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c
index 2e4e9127ed6..3ffb125cdde 100644
--- a/source/blender/editors/screen/screen_draw.c
+++ b/source/blender/editors/screen/screen_draw.c
@@ -213,7 +213,7 @@ static void draw_join_shape(ScrArea *sa, char dir, unsigned int pos)
*/
static void scrarea_draw_shape_dark(ScrArea *sa, char dir, unsigned int pos)
{
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
immUniformColor4ub(0, 0, 0, 50);
draw_join_shape(sa, dir, pos);
@@ -298,7 +298,7 @@ void ED_screen_draw_edges(wmWindow *win)
ScrArea *sa;
- wmSubWindowSet(win, screen->mainwin);
+ wmWindowViewport(win);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -485,6 +485,7 @@ static void screen_preview_draw(const bScreen *screen, int size_x, int size_y)
wmOrtho2(0.0f, size_x, 0.0f, size_y);
/* center */
gpuPushMatrix();
+ gpuLoadIdentity();
gpuTranslate2f(size_x * (1.0f - asp[0]) * 0.5f, size_y * (1.0f - asp[1]) * 0.5f);
screen_preview_scale_get(screen, size_x, size_y, asp, scale);
@@ -499,11 +500,11 @@ static void screen_preview_draw(const bScreen *screen, int size_x, int size_y)
void ED_screen_preview_render(const bScreen *screen, int size_x, int size_y, unsigned int *r_rect)
{
char err_out[256] = "unknown";
- GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, 0, false, err_out);
+ GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, 0, true, false, err_out);
GPU_offscreen_bind(offscreen, true);
glClearColor(0.0, 0.0, 0.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
screen_preview_draw(screen, size_x, size_y);
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 0b78590d4d8..e65fd2701b4 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -33,6 +33,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_workspace_types.h"
#include "DNA_userdef_types.h"
@@ -68,8 +69,7 @@
#include "WM_message.h"
-/* XXX actually should be not here... solve later */
-#include "wm_subwindow.h"
+#include "DEG_depsgraph_query.h"
#include "screen_intern.h" /* own module include */
@@ -848,14 +848,14 @@ static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y)
/* ****************** EXPORTED API TO OTHER MODULES *************************** */
-/* screen sets cursor based on swinid */
-static void region_cursor_set(wmWindow *win, int swinid, int swin_changed)
+/* screen sets cursor based on active region */
+static void region_cursor_set(wmWindow *win, bool swin_changed)
{
bScreen *screen = WM_window_get_active_screen(win);
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->swinid == swinid) {
+ if (ar == screen->active_region) {
if (swin_changed || (ar->type && ar->type->event_cursor)) {
if (ar->manipulator_map != NULL) {
if (WM_manipulatormap_cursor_set(ar->manipulator_map, win)) {
@@ -890,7 +890,7 @@ void ED_screen_do_listen(bContext *C, wmNotifier *note)
break;
case NC_SCENE:
if (note->data == ND_MODE)
- region_cursor_set(win, note->swinid, true);
+ region_cursor_set(win, true);
break;
}
}
@@ -918,12 +918,6 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
const int winsize_x = WM_window_pixels_x(win);
const int winsize_y = WM_window_pixels_y(win);
ScrArea *sa;
- rcti winrct;
-
- winrct.xmin = 0;
- winrct.xmax = winsize_x - 1;
- winrct.ymin = 0;
- winrct.ymax = winsize_y - 1;
/* header size depends on DPI, let's verify */
WM_window_set_dpi(win);
@@ -931,13 +925,6 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
screen_test_scale(screen, winsize_x, winsize_y);
- if (screen->mainwin == 0) {
- screen->mainwin = wm_subwindow_open(win, &winrct, false);
- }
- else {
- wm_subwindow_position(win, screen->mainwin, &winrct, false);
- }
-
for (sa = screen->areabase.first; sa; sa = sa->next) {
/* set spacetype and region callbacks, calls init() */
/* sets subwindows for regions, adds handlers */
@@ -989,10 +976,7 @@ void ED_region_exit(bContext *C, ARegion *ar)
WM_event_remove_handlers(C, &ar->handlers);
WM_event_modal_handler_region_replace(win, ar, NULL);
- if (ar->swinid) {
- wm_subwindow_close(win, ar->swinid);
- ar->swinid = 0;
- }
+ ar->visible = 0;
if (ar->headerstr) {
MEM_freeN(ar->headerstr);
@@ -1044,10 +1028,7 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
screen->animtimer = NULL;
screen->scrubbing = false;
- if (screen->mainwin)
- wm_subwindow_close(window, screen->mainwin);
- screen->mainwin = 0;
- screen->subwinactive = 0;
+ screen->active_region = NULL;
for (ar = screen->regionbase.first; ar; ar = ar->next)
ED_region_exit(C, ar);
@@ -1112,7 +1093,7 @@ static void screen_cursor_set(wmWindow *win, const wmEvent *event)
/* called in wm_event_system.c. sets state vars in screen, cursors */
/* event type is mouse move */
-void ED_screen_set_subwinactive(bContext *C, const wmEvent *event)
+void ED_screen_set_active_region(bContext *C, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
bScreen *scr = WM_window_get_active_screen(win);
@@ -1120,7 +1101,7 @@ void ED_screen_set_subwinactive(bContext *C, const wmEvent *event)
if (scr) {
ScrArea *sa;
ARegion *ar;
- int oldswin = scr->subwinactive;
+ ARegion *old_ar = scr->active_region;
for (sa = scr->areabase.first; sa; sa = sa->next) {
if (event->x > sa->totrct.xmin && event->x < sa->totrct.xmax)
@@ -1132,22 +1113,22 @@ void ED_screen_set_subwinactive(bContext *C, const wmEvent *event)
/* make overlap active when mouse over */
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (BLI_rcti_isect_pt_v(&ar->winrct, &event->x)) {
- scr->subwinactive = ar->swinid;
+ scr->active_region = ar;
break;
}
}
}
else
- scr->subwinactive = scr->mainwin;
+ scr->active_region = NULL;
/* check for redraw headers */
- if (oldswin != scr->subwinactive) {
+ if (old_ar != scr->active_region) {
for (sa = scr->areabase.first; sa; sa = sa->next) {
bool do_draw = false;
for (ar = sa->regionbase.first; ar; ar = ar->next)
- if (ar->swinid == oldswin || ar->swinid == scr->subwinactive)
+ if (ar == old_ar || ar == scr->active_region)
do_draw = true;
if (do_draw) {
@@ -1159,13 +1140,13 @@ void ED_screen_set_subwinactive(bContext *C, const wmEvent *event)
}
/* cursors, for time being set always on edges, otherwise aregion doesnt switch */
- if (scr->subwinactive == scr->mainwin) {
+ if (scr->active_region == NULL) {
screen_cursor_set(win, event);
}
else {
/* notifier invokes freeing the buttons... causing a bit too much redraws */
- if (oldswin != scr->subwinactive) {
- region_cursor_set(win, scr->subwinactive, true);
+ if (old_ar != scr->active_region) {
+ region_cursor_set(win, true);
/* this used to be a notifier, but needs to be done immediate
* because it can undo setting the right button as active due
@@ -1173,7 +1154,7 @@ void ED_screen_set_subwinactive(bContext *C, const wmEvent *event)
UI_screen_free_active_but(C, scr);
}
else
- region_cursor_set(win, scr->subwinactive, false);
+ region_cursor_set(win, false);
}
}
}
@@ -1192,7 +1173,7 @@ int ED_screen_area_active(const bContext *C)
return 1;
for (ar = sa->regionbase.first; ar; ar = ar->next)
- if (ar->swinid == sc->subwinactive)
+ if (ar == sc->active_region)
return 1;
}
return 0;
@@ -1260,7 +1241,7 @@ bScreen *screen_change_prepare(bScreen *screen_old, bScreen *screen_new, Main *b
return NULL;
}
-void screen_changed_update(bContext *C, wmWindow *win, bScreen *sc)
+void screen_change_update(bContext *C, wmWindow *win, bScreen *sc)
{
Scene *scene = WM_window_get_active_scene(win);
WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
@@ -1297,7 +1278,7 @@ bool ED_screen_change(bContext *C, bScreen *sc)
if (screen_new) {
WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
WM_window_set_active_screen(win, workspace, sc);
- screen_changed_update(C, win, screen_new);
+ screen_change_update(C, win, screen_new);
return true;
}
@@ -1729,8 +1710,10 @@ void ED_screen_animation_timer_update(bScreen *screen, int redraws, int refresh)
}
/* results in fully updated anim system */
-void ED_update_for_newframe(Main *bmain, Scene *scene, ViewLayer *view_layer, struct Depsgraph *depsgraph)
+void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph)
{
+ Scene *scene = DEG_get_input_scene(depsgraph);
+
#ifdef DURIAN_CAMERA_SWITCH
void *camera = BKE_scene_camera_switch_find(scene);
if (camera && scene->camera != camera) {
@@ -1746,7 +1729,7 @@ void ED_update_for_newframe(Main *bmain, Scene *scene, ViewLayer *view_layer, st
ED_clip_update_frame(bmain, scene->r.cfra);
/* this function applies the changes too */
- BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
/* composite */
if (scene->use_nodes && scene->nodetree)
@@ -1850,10 +1833,14 @@ bool ED_screen_stereo3d_required(const bScreen *screen, const Scene *scene)
* Find the scene displayed in \a screen.
* \note Assumes \a screen to be visible/active!
*/
-Scene *ED_screen_scene_find(const bScreen *screen, const wmWindowManager *wm)
+
+Scene *ED_screen_scene_find_with_window(const bScreen *screen, const wmWindowManager *wm, struct wmWindow **r_window)
{
for (wmWindow *win = wm->windows.first; win; win = win->next) {
if (WM_window_get_active_screen(win) == screen) {
+ if (r_window) {
+ *r_window = win;
+ }
return WM_window_get_active_scene(win);
}
}
@@ -1861,3 +1848,20 @@ Scene *ED_screen_scene_find(const bScreen *screen, const wmWindowManager *wm)
BLI_assert(0);
return NULL;
}
+
+
+Scene *ED_screen_scene_find(const bScreen *screen, const wmWindowManager *wm)
+{
+ return ED_screen_scene_find_with_window(screen, wm, NULL);
+}
+
+
+wmWindow *ED_screen_window_find(const bScreen *screen, const wmWindowManager *wm)
+{
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ if (WM_window_get_active_screen(win) == screen) {
+ return win;
+ }
+ }
+ return NULL;
+}
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
index df92ab86ef2..6d0a9f1e7d0 100644
--- a/source/blender/editors/screen/screen_intern.h
+++ b/source/blender/editors/screen/screen_intern.h
@@ -50,7 +50,7 @@ void region_toggle_hidden(struct bContext *C, ARegion *ar, const bool do_
bScreen *screen_add(const char *name, const int winsize_x, const int winsize_y);
void screen_data_copy(bScreen *to, bScreen *from);
void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new);
-void screen_changed_update(struct bContext *C, wmWindow *win, bScreen *sc);
+void screen_change_update(struct bContext *C, wmWindow *win, bScreen *sc);
bScreen *screen_change_prepare(bScreen *screen_old, bScreen *screen_new, struct Main *bmain, struct bContext *C, wmWindow *win);
ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2);
ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge);
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 030c24b0061..898010858b9 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -69,6 +69,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "DEG_depsgraph.h"
+
#include "ED_armature.h"
#include "ED_clip.h"
#include "ED_image.h"
@@ -78,6 +80,7 @@
#include "ED_screen_types.h"
#include "ED_sequencer.h"
#include "ED_util.h"
+#include "ED_undo.h"
#include "ED_view3d.h"
#include "RNA_access.h"
@@ -137,7 +140,7 @@ int ED_operator_screen_mainwinactive(bContext *C)
if (CTX_wm_window(C) == NULL) return 0;
screen = CTX_wm_screen(C);
if (screen == NULL) return 0;
- if (screen->subwinactive != screen->mainwin) return 0;
+ if (screen->active_region != NULL) return 0;
return 1;
}
@@ -556,7 +559,7 @@ int ED_operator_mask(bContext *C)
{
SpaceImage *sima = sa->spacedata.first;
ViewLayer *view_layer = CTX_data_view_layer(C);
- return ED_space_image_check_show_maskedit(view_layer, sima);
+ return ED_space_image_check_show_maskedit(sima, view_layer);
}
}
}
@@ -887,23 +890,23 @@ static void SCREEN_OT_actionzone(wmOperatorType *ot)
/** \name Swap Area Operator
* \{ */
-/* operator state vars used:
- * sa1 start area
- * sa2 area to swap with
- *
+/* operator state vars used:
+ * sa1 start area
+ * sa2 area to swap with
+ *
* functions:
- *
+ *
* init() set custom data for operator, based on actionzone event custom data
- *
- * cancel() cancel the operator
- *
- * exit() cleanup, send notifier
- *
+ *
+ * cancel() cancel the operator
+ *
+ * exit() cleanup, send notifier
+ *
* callbacks:
- *
+ *
* invoke() gets called on shift+lmb drag in actionzone
* call init(), add handler
- *
+ *
* modal() accept modal events while doing it
*/
@@ -1444,35 +1447,35 @@ static void SCREEN_OT_area_move(wmOperatorType *ot)
/** \name Split Area Operator
* \{ */
-/*
- * operator state vars:
+/*
+ * operator state vars:
* fac spit point
* dir direction 'v' or 'h'
- *
+ *
* operator customdata:
* area pointer to (active) area
- * x, y last used mouse pos
+ * x, y last used mouse pos
* (more, see below)
- *
+ *
* functions:
- *
+ *
* init() set default property values, find area based on context
- *
- * apply() split area based on state vars
- *
- * exit() cleanup, send notifier
- *
+ *
+ * apply() split area based on state vars
+ *
+ * exit() cleanup, send notifier
+ *
* cancel() remove duplicated area
- *
+ *
* callbacks:
- *
+ *
* exec() execute without any user interaction, based on state vars
* call init(), apply(), exit()
- *
+ *
* invoke() gets called on mouse click in action-widget
* call init(), add modal handler
* call apply() with initial motion
- *
+ *
* modal() accept modal events while doing it
* call move-areas code with delta motion
* call exit() or cancel() and remove handler
@@ -3570,7 +3573,6 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
if (screen->animtimer && screen->animtimer == event->customdata) {
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
wmTimer *wt = screen->animtimer;
ScreenAnimData *sad = wt->customdata;
@@ -3682,7 +3684,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
}
/* since we follow drawflags, we can't send notifier but tag regions ourselves */
- ED_update_for_newframe(bmain, scene, view_layer, depsgraph);
+ ED_update_for_newframe(bmain, depsgraph);
for (window = wm->windows.first; window; window = window->next) {
const bScreen *win_screen = WM_window_get_active_screen(window);
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index 00dc1003121..ace3f17542e 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -36,6 +36,7 @@
#include "BKE_context.h"
#include "BKE_idcode.h"
#include "BKE_main.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -55,6 +56,9 @@
#include "MEM_guardedalloc.h"
#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "DEG_depsgraph.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -79,14 +83,9 @@ WorkSpace *ED_workspace_add(
BKE_workspace_view_layer_set(workspace, act_view_layer, scene);
BKE_viewrender_copy(&workspace->view_render, view_render);
-#ifdef USE_WORKSPACE_MODE
- BKE_workspace_object_mode_set(workspace, scene, OB_MODE_OBJECT);
-#endif
-
return workspace;
}
-#ifdef USE_WORKSPACE_MODE
/**
* Changes the object mode (if needed) to the one set in \a workspace_new.
* Object mode is still stored on object level. In future it should all be workspace level instead.
@@ -95,16 +94,17 @@ static void workspace_change_update_mode(
const WorkSpace *workspace_old, const WorkSpace *workspace_new,
bContext *C, Object *ob_act, ReportList *reports)
{
- const Scene *scene = CTX_data_scene(C);
- eObjectMode mode_old = BKE_workspace_object_mode_get(workspace_old, scene);
- eObjectMode mode_new = BKE_workspace_object_mode_get(workspace_new, scene);
+ UNUSED_VARS(workspace_old, workspace_new, C, ob_act, reports);
+#if 0
+ eObjectMode mode_old = workspace_old->object_mode;
+ eObjectMode mode_new = workspace_new->object_mode;
if (mode_old != mode_new) {
ED_object_mode_compat_set(C, ob_act, mode_new, reports);
- ED_object_toggle_modes(C, mode_new);
+ ED_object_mode_toggle(C, mode_new);
}
-}
#endif
+}
static void workspace_change_update_view_layer(
WorkSpace *workspace_new, const WorkSpace *workspace_old,
@@ -121,11 +121,7 @@ static void workspace_change_update(
{
/* needs to be done before changing mode! (to ensure right context) */
workspace_change_update_view_layer(workspace_new, workspace_old, CTX_data_scene(C));
-#ifdef USE_WORKSPACE_MODE
workspace_change_update_mode(workspace_old, workspace_new, C, CTX_data_active_object(C), &wm->reports);
-#else
- UNUSED_VARS(C, wm);
-#endif
}
static bool workspace_change_find_new_layout_cb(const WorkSpaceLayout *layout, void *UNUSED(arg))
@@ -198,8 +194,9 @@ bool ED_workspace_change(
WM_window_set_active_layout(win, workspace_new, layout_new);
WM_window_set_active_workspace(win, workspace_new);
- /* update screen *after* changing workspace - which also causes the actual screen change */
- screen_changed_update(C, win, screen_new);
+ /* update screen *after* changing workspace - which also causes the
+ * actual screen change and updates context (including CTX_wm_workspace) */
+ screen_change_update(C, win, screen_new);
workspace_change_update(workspace_new, workspace_old, C, wm);
BLI_assert(BKE_workspace_view_layer_get(workspace_new, CTX_data_scene(C)) != NULL);
@@ -231,9 +228,6 @@ WorkSpace *ED_workspace_duplicate(
ListBase *transform_orientations_old = BKE_workspace_transform_orientations_get(workspace_old);
ListBase *transform_orientations_new = BKE_workspace_transform_orientations_get(workspace_new);
-#ifdef USE_WORKSPACE_MODE
- BKE_workspace_object_mode_set(workspace_new, scene, BKE_workspace_object_mode_get(workspace_old, scene));
-#endif
BLI_duplicatelist(transform_orientations_new, transform_orientations_old);
workspace_new->tool = workspace_old->tool;
@@ -345,6 +339,66 @@ static void WORKSPACE_OT_workspace_delete(wmOperatorType *ot)
ot->exec = workspace_delete_exec;
}
+static int workspace_append(bContext *C, const char *directory, const char *idname)
+{
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
+ PointerRNA opptr;
+ int retval;
+
+ WM_operator_properties_create_ptr(&opptr, ot);
+ RNA_string_set(&opptr, "directory", directory);
+ RNA_string_set(&opptr, "filename", idname);
+ RNA_boolean_set(&opptr, "autoselect", false);
+
+ retval = WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &opptr);
+
+ WM_operator_properties_free(&opptr);
+
+ return retval;
+}
+
+static int workspace_append_activate_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ char idname[MAX_ID_NAME - 2], directory[FILE_MAX];
+
+ if (!RNA_struct_property_is_set(op->ptr, "idname") ||
+ !RNA_struct_property_is_set(op->ptr, "directory"))
+ {
+ return OPERATOR_CANCELLED;
+ }
+ RNA_string_get(op->ptr, "idname", idname);
+ RNA_string_get(op->ptr, "directory", directory);
+
+ if (workspace_append(C, directory, idname) != OPERATOR_CANCELLED) {
+ WorkSpace *appended_workspace = BLI_findstring(&bmain->workspaces, idname, offsetof(ID, name) + 2);
+
+ BLI_assert(appended_workspace != NULL);
+ /* Changing workspace changes context. Do delayed! */
+ WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+static void WORKSPACE_OT_append_activate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Append and Activate Workspace";
+ ot->description = "Append a workspace and make it the active one in the current window";
+ ot->idname = "WORKSPACE_OT_append_activate";
+
+ /* api callbacks */
+ ot->exec = workspace_append_activate_exec;
+
+ RNA_def_string(ot->srna, "idname", NULL, MAX_ID_NAME - 2, "Identifier",
+ "Name of the workspace to append and activate");
+ RNA_def_string(ot->srna, "directory", NULL, FILE_MAX, "Directory",
+ "Path to the library");
+}
+
static void workspace_config_file_path_from_folder_id(
const Main *bmain, int folder_id, char *r_path)
{
@@ -390,13 +444,12 @@ static void workspace_append_button(
BLI_path_join(
lib_path, sizeof(lib_path), from_main->name, BKE_idcode_to_name(GS(id->name)), NULL);
- BLI_assert(STREQ(ot_append->idname, "WM_OT_append"));
+ BLI_assert(STREQ(ot_append->idname, "WORKSPACE_OT_append_activate"));
uiItemFullO_ptr(
layout, ot_append, workspace->id.name + 2, ICON_NONE, NULL,
WM_OP_EXEC_DEFAULT, 0, &opptr);
+ RNA_string_set(&opptr, "idname", id->name + 2);
RNA_string_set(&opptr, "directory", lib_path);
- RNA_string_set(&opptr, "filename", id->name + 2);
- RNA_boolean_set(&opptr, "autoselect", false);
}
ATTR_NONNULL(1, 2)
@@ -406,7 +459,7 @@ static void workspace_config_file_append_buttons(
WorkspaceConfigFileData *workspace_config = workspace_config_file_read(bmain, reports);
if (workspace_config) {
- wmOperatorType *ot_append = WM_operatortype_find("WM_OT_append", true);
+ wmOperatorType *ot_append = WM_operatortype_find("WORKSPACE_OT_append_activate", true);
for (WorkSpace *workspace = workspace_config->workspaces.first; workspace; workspace = workspace->id.next) {
workspace_append_button(layout, ot_append, workspace, workspace_config->main);
@@ -449,6 +502,7 @@ void ED_operatortypes_workspace(void)
WM_operatortype_append(WORKSPACE_OT_workspace_duplicate);
WM_operatortype_append(WORKSPACE_OT_workspace_delete);
WM_operatortype_append(WORKSPACE_OT_workspace_add_menu);
+ WM_operatortype_append(WORKSPACE_OT_append_activate);
}
/** \} Workspace Operators */
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index b3e125baae3..80c58e5b91d 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -43,14 +43,15 @@ set(INC_SYS
set(SRC
paint_cursor.c
paint_curve.c
+ paint_curve_undo.c
paint_hide.c
paint_image.c
paint_image_2d.c
paint_image_proj.c
+ paint_image_undo.c
paint_mask.c
paint_ops.c
paint_stroke.c
- paint_undo.c
paint_utils.c
paint_vertex.c
paint_vertex_color_ops.c
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 3a43c7a6585..6229b91a518 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -338,6 +338,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
size = target->old_size;
}
+ glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, target->overlay_texture);
if (refresh) {
@@ -464,6 +465,7 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
size = cursor_snap.size;
}
+ glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, cursor_snap.overlay_texture);
if (refresh) {
@@ -767,7 +769,7 @@ static void paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush,
/* draw textured quad */
/* draw textured quad */
- immUniform1i("image", GL_TEXTURE0);
+ immUniform1i("image", 0);
immBegin(GWN_PRIM_TRI_FAN, 4);
immAttrib2f(texCoord, 0.0f, 0.0f);
@@ -1033,7 +1035,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* can't use stroke vc here because this will be called during
* mouse over too, not just during a stroke */
ViewContext vc;
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
if (vc.rv3d && (vc.rv3d->rflag & RV3D_NAVIGATING)) {
return;
diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c
index 337f7a1ef2b..049d8ff8c0b 100644
--- a/source/blender/editors/sculpt_paint/paint_curve.c
+++ b/source/blender/editors/sculpt_paint/paint_curve.c
@@ -34,14 +34,15 @@
#include "DNA_view3d_types.h"
#include "BLI_math_vector.h"
-#include "BLI_string.h"
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_paint.h"
-#include "ED_paint.h"
+#include "DEG_depsgraph.h"
+
#include "ED_view3d.h"
+#include "ED_paint.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -56,7 +57,6 @@
#define PAINT_CURVE_SELECT_THRESHOLD 40.0f
#define PAINT_CURVE_POINT_SELECT(pcp, i) (*(&pcp->bez.f1 + i) = SELECT)
-
int paint_curve_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
@@ -81,91 +81,6 @@ int paint_curve_poll(bContext *C)
return false;
}
-/* Paint Curve Undo*/
-
-typedef struct UndoCurve {
- struct UndoImageTile *next, *prev;
-
- PaintCurvePoint *points; /* points of curve */
- int tot_points;
- int active_point;
-
- char idname[MAX_ID_NAME]; /* name instead of pointer*/
-} UndoCurve;
-
-static void paintcurve_undo_restore(bContext *C, ListBase *lb)
-{
- Paint *p = BKE_paint_get_active_from_context(C);
- UndoCurve *uc;
- PaintCurve *pc = NULL;
-
- if (p->brush) {
- pc = p->brush->paint_curve;
- }
-
- if (!pc)
- return;
-
- uc = (UndoCurve *)lb->first;
-
- if (STREQLEN(uc->idname, pc->id.name, BLI_strnlen(uc->idname, sizeof(uc->idname)))) {
- SWAP(PaintCurvePoint *, pc->points, uc->points);
- SWAP(int, pc->tot_points, uc->tot_points);
- SWAP(int, pc->add_index, uc->active_point);
- }
-}
-
-static void paintcurve_undo_delete(ListBase *lb)
-{
- UndoCurve *uc;
- uc = (UndoCurve *)lb->first;
-
- if (uc->points)
- MEM_freeN(uc->points);
- uc->points = NULL;
-}
-
-
-static void paintcurve_undo_begin(bContext *C, wmOperator *op, PaintCurve *pc)
-{
- ePaintMode mode = BKE_paintmode_get_active_from_context(C);
- ListBase *lb = NULL;
- int undo_stack_id;
- UndoCurve *uc;
-
- switch (mode) {
- case ePaintTexture2D:
- case ePaintTextureProjective:
- undo_stack_id = UNDO_PAINT_IMAGE;
- break;
-
- case ePaintSculpt:
- undo_stack_id = UNDO_PAINT_MESH;
- break;
-
- default:
- /* do nothing, undo is handled by global */
- return;
- }
-
-
- ED_undo_paint_push_begin(undo_stack_id, op->type->name,
- paintcurve_undo_restore, paintcurve_undo_delete, NULL);
- lb = undo_paint_push_get_list(undo_stack_id);
-
- uc = MEM_callocN(sizeof(*uc), "Undo_curve");
-
- lb->first = uc;
-
- BLI_strncpy(uc->idname, pc->id.name, sizeof(uc->idname));
- uc->tot_points = pc->tot_points;
- uc->active_point = pc->add_index;
- uc->points = MEM_dupallocN(pc->points);
-
- undo_paint_push_count_alloc(undo_stack_id, sizeof(*uc) + sizeof(*pc->points) * pc->tot_points);
-
- ED_undo_paint_push_end(undo_stack_id);
-}
#define SEL_F1 (1 << 0)
#define SEL_F2 (1 << 1)
#define SEL_F3 (1 << 2)
@@ -291,7 +206,7 @@ static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2])
br->paint_curve = pc = BKE_paint_curve_add(bmain, "PaintCurve");
}
- paintcurve_undo_begin(C, op, pc);
+ ED_paintcurve_undo_push_begin(op->type->name);
pcp = MEM_mallocN((pc->tot_points + 1) * sizeof(PaintCurvePoint), "PaintCurvePoint");
add_index = pc->add_index;
@@ -329,6 +244,8 @@ static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2])
pcp[add_index].bez.h1 = HD_ALIGN;
}
+ ED_paintcurve_undo_push_end();
+
WM_paint_cursor_tag_redraw(window, ar);
}
@@ -390,7 +307,7 @@ static int paintcurve_delete_point_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- paintcurve_undo_begin(C, op, pc);
+ ED_paintcurve_undo_push_begin(op->type->name);
#define DELETE_TAG 2
@@ -430,6 +347,8 @@ static int paintcurve_delete_point_exec(bContext *C, wmOperator *op)
#undef DELETE_TAG
+ ED_paintcurve_undo_push_end();
+
WM_paint_cursor_tag_redraw(window, ar);
return OPERATOR_FINISHED;
@@ -467,7 +386,7 @@ static bool paintcurve_point_select(bContext *C, wmOperator *op, const int loc[2
if (!pc)
return false;
- paintcurve_undo_begin(C, op, pc);
+ ED_paintcurve_undo_push_begin(op->type->name);
if (toggle) {
PaintCurvePoint *pcp;
@@ -532,10 +451,14 @@ static bool paintcurve_point_select(bContext *C, wmOperator *op, const int loc[2
}
}
- if (!pcp)
+ if (!pcp) {
+ ED_paintcurve_undo_push_end();
return false;
+ }
}
+ ED_paintcurve_undo_push_end();
+
WM_paint_cursor_tag_redraw(window, ar);
return true;
@@ -650,9 +573,6 @@ static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *e
psd->align = align;
op->customdata = psd;
- if (do_select)
- paintcurve_undo_begin(C, op, pc);
-
/* first, clear all selection from points */
for (i = 0; i < pc->tot_points; i++)
pc->points[i].bez.f1 = pc->points[i].bez.f3 = pc->points[i].bez.f2 = 0;
@@ -675,6 +595,8 @@ static int paintcurve_slide_modal(bContext *C, wmOperator *op, const wmEvent *ev
if (event->type == psd->event && event->val == KM_RELEASE) {
MEM_freeN(psd);
+ ED_paintcurve_undo_push_begin(op->type->name);
+ ED_paintcurve_undo_push_end();
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/sculpt_paint/paint_curve_undo.c b/source/blender/editors/sculpt_paint/paint_curve_undo.c
new file mode 100644
index 00000000000..77f06180df6
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_curve_undo.c
@@ -0,0 +1,168 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/sculpt_paint/paint_curve_undo.c
+ * \ingroup edsculpt
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_space_types.h"
+
+#include "BLI_string.h"
+#include "BLI_array_utils.h"
+
+#include "BKE_context.h"
+#include "BKE_paint.h"
+#include "BKE_undo_system.h"
+
+#include "ED_paint.h"
+#include "ED_undo.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "paint_intern.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Undo Conversion
+ * \{ */
+
+typedef struct UndoCurve {
+ PaintCurvePoint *points; /* points of curve */
+ int tot_points;
+ int add_index;
+} UndoCurve;
+
+static void undocurve_from_paintcurve(UndoCurve *uc, const PaintCurve *pc)
+{
+ BLI_assert(BLI_array_is_zeroed(uc, 1));
+ uc->points = MEM_dupallocN(pc->points);
+ uc->tot_points = pc->tot_points;
+ uc->add_index = pc->add_index;
+}
+
+static void undocurve_to_paintcurve(const UndoCurve *uc, PaintCurve *pc)
+{
+ MEM_SAFE_FREE(pc->points);
+ pc->points = MEM_dupallocN(uc->points);
+ pc->tot_points = uc->tot_points;
+ pc->add_index = uc->add_index;
+}
+
+static void undocurve_free_data(UndoCurve *uc)
+{
+ MEM_SAFE_FREE(uc->points);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Implements ED Undo System
+ * \{ */
+
+typedef struct PaintCurveUndoStep {
+ UndoStep step;
+ PaintCurve *pc;
+ UndoCurve data;
+} PaintCurveUndoStep;
+
+static bool paintcurve_undosys_poll(bContext *C)
+{
+ Paint *p = BKE_paint_get_active_from_context(C);
+ return (p->brush && p->brush->paint_curve);
+}
+
+static void paintcurve_undosys_step_encode_init(struct bContext *C, UndoStep *us_p)
+{
+ /* XXX, use to set the undo type only. */
+ UNUSED_VARS(C, us_p);
+}
+
+static bool paintcurve_undosys_step_encode(struct bContext *C, UndoStep *us_p)
+{
+ Paint *p = BKE_paint_get_active_from_context(C);
+ PaintCurve *pc = p ? (p->brush ? p->brush->paint_curve : NULL) : NULL;
+ if (pc == NULL) {
+ return false;
+ }
+
+ PaintCurveUndoStep *us = (PaintCurveUndoStep *)us_p;
+ BLI_assert(us->step.data_size == 0);
+
+ us->pc = pc;
+ undocurve_from_paintcurve(&us->data, pc);
+
+ return true;
+}
+
+static void paintcurve_undosys_step_decode(struct bContext *UNUSED(C), UndoStep *us_p, int UNUSED(dir))
+{
+ PaintCurveUndoStep *us = (PaintCurveUndoStep *)us_p;
+ undocurve_to_paintcurve(&us->data, us->pc);
+}
+
+static void paintcurve_undosys_step_free(UndoStep *us_p)
+{
+ PaintCurveUndoStep *us = (PaintCurveUndoStep *)us_p;
+ undocurve_free_data(&us->data);
+}
+
+/* Export for ED_undo_sys. */
+void ED_paintcurve_undosys_type(UndoType *ut)
+{
+ ut->name = "Paint Curve";
+ /* don't poll for now */
+ ut->poll = paintcurve_undosys_poll;
+ ut->step_encode_init = paintcurve_undosys_step_encode_init;
+ ut->step_encode = paintcurve_undosys_step_encode;
+ ut->step_decode = paintcurve_undosys_step_decode;
+ ut->step_free = paintcurve_undosys_step_free;
+
+ ut->mode = BKE_UNDOTYPE_MODE_STORE;
+ ut->use_context = false;
+
+ ut->step_size = sizeof(PaintCurveUndoStep);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/** \name Utilities
+ * \{ */
+
+void ED_paintcurve_undo_push_begin(const char *name)
+{
+ UndoStack *ustack = ED_undo_stack_get();
+ bContext *C = NULL; /* special case, we never read from this. */
+ BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_PAINTCURVE);
+}
+
+void ED_paintcurve_undo_push_end(void)
+{
+ UndoStack *ustack = ED_undo_stack_get();
+ BKE_undosys_step_push(ustack, NULL, NULL);
+}
+
+/** \} */
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index 8377b22756e..4d3c8fe4d5c 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -325,7 +325,7 @@ static void clip_planes_from_rect(bContext *C,
BoundBox bb;
view3d_operator_needs_opengl(C);
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
ED_view3d_clipping_calc(&bb, clip_planes, vc.ar, vc.obact, rect);
negate_m4(clip_planes);
}
@@ -418,7 +418,7 @@ static int hide_show_exec(bContext *C, wmOperator *op)
MEM_freeN(nodes);
/* end undo */
- sculpt_undo_push_end(C);
+ sculpt_undo_push_end();
/* ensure that edges and faces get hidden as well (not used by
* sculpt but it looks wrong when entering editmode otherwise) */
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index aebd0c10e9c..ae26de8b269 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -39,7 +39,6 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BLI_threads.h"
#include "BLT_translation.h"
@@ -54,11 +53,12 @@
#include "BKE_context.h"
#include "BKE_DerivedMesh.h"
#include "BKE_brush.h"
-#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_node.h"
#include "BKE_paint.h"
+#include "BKE_undo_system.h"
+
#include "DEG_depsgraph.h"
@@ -87,43 +87,10 @@
#include "paint_intern.h"
-typedef struct UndoImageTile {
- struct UndoImageTile *next, *prev;
-
- char idname[MAX_ID_NAME]; /* name instead of pointer*/
- char ibufname[IMB_FILENAME_SIZE];
-
- union {
- float *fp;
- unsigned int *uint;
- void *pt;
- } rect;
-
- unsigned short *mask;
-
- int x, y;
-
- Image *ima;
- short source, use_float;
- char gen_type;
- bool valid;
-} UndoImageTile;
-
/* this is a static resource for non-globality,
* Maybe it should be exposed as part of the
* paint operation, but for now just give a public interface */
static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0};
-static SpinLock undolock;
-
-void image_undo_init_locks(void)
-{
- BLI_spin_init(&undolock);
-}
-
-void image_undo_end_locks(void)
-{
- BLI_spin_end(&undolock);
-}
ImagePaintPartialRedraw *get_imapaintpartial(void)
{
@@ -135,296 +102,6 @@ void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr)
imapaintpartial = *ippr;
}
-/* UNDO */
-typedef enum {
- COPY = 0,
- RESTORE = 1,
- RESTORE_COPY = 2
-} CopyMode;
-
-static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, CopyMode mode)
-{
- if (mode == COPY) {
- /* copy or swap contents of tile->rect and region in ibuf->rect */
- IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
- tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
-
- if (ibuf->rect_float) {
- SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
- }
- else {
- SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
- }
- }
- else {
- if (mode == RESTORE_COPY) {
- IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
- tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
- }
- /* swap to the tmpbuf for easy copying */
- if (ibuf->rect_float) {
- SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
- }
- else {
- SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
- }
-
- IMB_rectcpy(ibuf, tmpibuf, tile->x * IMAPAINT_TILE_SIZE,
- tile->y * IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
-
- if (mode == RESTORE) {
- if (ibuf->rect_float) {
- SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
- }
- else {
- SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
- }
- }
- }
-}
-
-void *image_undo_find_tile(Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask, bool validate)
-{
- ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
- UndoImageTile *tile;
- short use_float = ibuf->rect_float ? 1 : 0;
-
- for (tile = lb->first; tile; tile = tile->next) {
- if (tile->x == x_tile && tile->y == y_tile && ima->gen_type == tile->gen_type && ima->source == tile->source) {
- if (tile->use_float == use_float) {
- if (STREQ(tile->idname, ima->id.name) && STREQ(tile->ibufname, ibuf->name)) {
- if (mask) {
- /* allocate mask if requested */
- if (!tile->mask) {
- tile->mask = MEM_callocN(sizeof(unsigned short) * IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE,
- "UndoImageTile.mask");
- }
-
- *mask = tile->mask;
- }
- if (validate)
- tile->valid = true;
-
- return tile->rect.pt;
- }
- }
- }
- }
-
- return NULL;
-}
-
-void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **mask, bool **valid, bool proj, bool find_prev)
-{
- ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
- UndoImageTile *tile;
- int allocsize;
- short use_float = ibuf->rect_float ? 1 : 0;
- void *data;
-
- /* check if tile is already pushed */
-
- /* in projective painting we keep accounting of tiles, so if we need one pushed, just push! */
- if (find_prev) {
- data = image_undo_find_tile(ima, ibuf, x_tile, y_tile, mask, true);
- if (data)
- return data;
- }
-
- if (*tmpibuf == NULL)
- *tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect);
-
- tile = MEM_callocN(sizeof(UndoImageTile), "UndoImageTile");
- BLI_strncpy(tile->idname, ima->id.name, sizeof(tile->idname));
- tile->x = x_tile;
- tile->y = y_tile;
-
- /* add mask explicitly here */
- if (mask)
- *mask = tile->mask = MEM_callocN(sizeof(unsigned short) * IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE,
- "UndoImageTile.mask");
-
- allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
- allocsize *= (ibuf->rect_float) ? sizeof(float) : sizeof(char);
- tile->rect.pt = MEM_mapallocN(allocsize, "UndeImageTile.rect");
-
- BLI_strncpy(tile->ibufname, ibuf->name, sizeof(tile->ibufname));
-
- tile->gen_type = ima->gen_type;
- tile->source = ima->source;
- tile->use_float = use_float;
- tile->valid = true;
- tile->ima = ima;
-
- if (valid)
- *valid = &tile->valid;
-
- undo_copy_tile(tile, *tmpibuf, ibuf, COPY);
-
- if (proj)
- BLI_spin_lock(&undolock);
-
- undo_paint_push_count_alloc(UNDO_PAINT_IMAGE, allocsize);
- BLI_addtail(lb, tile);
-
- if (proj)
- BLI_spin_unlock(&undolock);
-
- return tile->rect.pt;
-}
-
-void image_undo_remove_masks(void)
-{
- ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
- UndoImageTile *tile;
-
- for (tile = lb->first; tile; tile = tile->next) {
- if (tile->mask) {
- MEM_freeN(tile->mask);
- tile->mask = NULL;
- }
- }
-}
-
-static void image_undo_restore_runtime(ListBase *lb)
-{
- ImBuf *ibuf, *tmpibuf;
- UndoImageTile *tile;
-
- tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32,
- IB_rectfloat | IB_rect);
-
- for (tile = lb->first; tile; tile = tile->next) {
- Image *ima = tile->ima;
- ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
-
- undo_copy_tile(tile, tmpibuf, ibuf, RESTORE);
-
- GPU_free_image(ima); /* force OpenGL reload (maybe partial update will operate better?) */
- if (ibuf->rect_float)
- ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
- if (ibuf->mipmap[0])
- ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
-
- IMB_freeImBuf(tmpibuf);
-}
-
-void ED_image_undo_restore(bContext *C, ListBase *lb)
-{
- Main *bmain = CTX_data_main(C);
- Image *ima = NULL;
- ImBuf *ibuf, *tmpibuf;
- UndoImageTile *tile;
-
- tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32,
- IB_rectfloat | IB_rect);
-
- for (tile = lb->first; tile; tile = tile->next) {
- short use_float;
-
- /* find image based on name, pointer becomes invalid with global undo */
- if (ima && STREQ(tile->idname, ima->id.name)) {
- /* ima is valid */
- }
- else {
- ima = BLI_findstring(&bmain->image, tile->idname, offsetof(ID, name));
- }
-
- ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
-
- if (ima && ibuf && !STREQ(tile->ibufname, ibuf->name)) {
- /* current ImBuf filename was changed, probably current frame
- * was changed when painting on image sequence, rather than storing
- * full image user (which isn't so obvious, btw) try to find ImBuf with
- * matched file name in list of already loaded images */
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
-
- ibuf = BKE_image_get_ibuf_with_name(ima, tile->ibufname);
- }
-
- if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- continue;
- }
-
- if (ima->gen_type != tile->gen_type || ima->source != tile->source) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- continue;
- }
-
- use_float = ibuf->rect_float ? 1 : 0;
-
- if (use_float != tile->use_float) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- continue;
- }
-
- undo_copy_tile(tile, tmpibuf, ibuf, RESTORE_COPY);
-
- GPU_free_image(ima); /* force OpenGL reload */
- if (ibuf->rect_float)
- ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
- if (ibuf->mipmap[0])
- ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
-
- DEG_id_tag_update(&ima->id, 0);
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
-
- IMB_freeImBuf(tmpibuf);
-}
-
-void ED_image_undo_free(ListBase *lb)
-{
- UndoImageTile *tile;
-
- for (tile = lb->first; tile; tile = tile->next)
- MEM_freeN(tile->rect.pt);
-}
-
-static void image_undo_end(void)
-{
- ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
- UndoImageTile *tile;
- int deallocsize = 0;
- int allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
-
- /* first dispose of invalid tiles (may happen due to drag dot for instance) */
- for (tile = lb->first; tile;) {
- if (!tile->valid) {
- UndoImageTile *tmp_tile = tile->next;
- deallocsize += allocsize * ((tile->use_float) ? sizeof(float) : sizeof(char));
- MEM_freeN(tile->rect.pt);
- BLI_freelinkN(lb, tile);
- tile = tmp_tile;
- }
- else {
- tile = tile->next;
- }
- }
-
- /* don't forget to remove the size of deallocated tiles */
- undo_paint_push_count_alloc(UNDO_PAINT_IMAGE, -deallocsize);
-
- ED_undo_paint_push_end(UNDO_PAINT_IMAGE);
-}
-
-static void image_undo_invalidate(void)
-{
- UndoImageTile *tile;
- ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
-
- for (tile = lb->first; tile; tile = tile->next)
- tile->valid = false;
-}
-
/* Imagepaint Partial Redraw & Dirty Region */
void ED_imapaint_clear_partial_redraw(void)
@@ -454,7 +131,7 @@ void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int
if (w == 0 || h == 0)
return;
-
+
if (!imapaintpartial.enabled) {
imapaintpartial.x1 = x;
imapaintpartial.y1 = y;
@@ -471,12 +148,14 @@ void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int
imapaint_region_tiles(ibuf, x, y, w, h, &tilex, &tiley, &tilew, &tileh);
+ ListBase *undo_tiles = ED_image_undo_get_tiles();
+
for (ty = tiley; ty <= tileh; ty++)
for (tx = tilex; tx <= tilew; tx++)
- image_undo_push_tile(ima, ibuf, &tmpibuf, tx, ty, NULL, NULL, false, find_old);
+ image_undo_push_tile(undo_tiles, ima, ibuf, &tmpibuf, tx, ty, NULL, NULL, false, find_old);
ibuf->userflags |= IB_BITMAPDIRTY;
-
+
if (tmpibuf)
IMB_freeImBuf(tmpibuf);
}
@@ -656,8 +335,9 @@ bool paint_use_opacity_masking(Brush *brush)
false : true;
}
-void paint_brush_color_get(struct Scene *scene, struct Brush *br, bool color_correction, bool invert, float distance,
- float pressure, float color[3], struct ColorManagedDisplay *display)
+void paint_brush_color_get(
+ struct Scene *scene, struct Brush *br, bool color_correction, bool invert, float distance,
+ float pressure, float color[3], struct ColorManagedDisplay *display)
{
if (invert)
copy_v3_v3(color, BKE_brush_secondary_color_get(scene, br));
@@ -758,7 +438,7 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo
PaintOperation *pop = MEM_callocN(sizeof(PaintOperation), "PaintOperation"); /* caller frees */
Brush *brush = BKE_paint_brush(&settings->imapaint.paint);
int mode = RNA_enum_get(op->ptr, "mode");
- view3d_set_viewcontext(C, &pop->vc);
+ ED_view3d_viewcontext_init(C, &pop->vc);
copy_v2_v2(pop->prevmouse, mouse);
copy_v2_v2(pop->startmouse, mouse);
@@ -792,20 +472,11 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo
}
settings->imapaint.flag |= IMAGEPAINT_DRAWING;
- ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
- ED_image_undo_restore, ED_image_undo_free, NULL);
+ ED_image_undo_push_begin(op->type->name);
return pop;
}
-/* restore painting image to previous state. Used for anchored and drag-dot style brushes*/
-static void paint_stroke_restore(void)
-{
- ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
- image_undo_restore_runtime(lb);
- image_undo_invalidate();
-}
-
static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
{
PaintOperation *pop = paint_stroke_mode_data(stroke);
@@ -842,7 +513,8 @@ static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, Po
BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * alphafac));
if ((brush->flag & BRUSH_DRAG_DOT) || (brush->flag & BRUSH_ANCHORED)) {
- paint_stroke_restore();
+ UndoStack *ustack = CTX_wm_manager(C)->undo_stack;
+ ED_image_undo_restore(ustack->step_init);
}
if (pop->mode == PAINT_MODE_3D_PROJECT) {
@@ -919,7 +591,7 @@ static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
WM_paint_cursor_end(CTX_wm_manager(C), pop->cursor);
}
- image_undo_end();
+ ED_image_undo_push_end();
/* duplicate warning, see texpaint_init */
#if 0
@@ -1426,8 +1098,10 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)sl;
- if (!sima->pin)
- ED_space_image_set(sima, scene, scene->obedit, ima);
+ if (!sima->pin) {
+ Object *obedit = CTX_data_edit_object(C);
+ ED_space_image_set(sima, scene, obedit, ima);
+ }
}
}
}
@@ -1445,6 +1119,8 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
toggle_paint_cursor(C, 1);
}
+ // ED_workspace_object_mode_sync_from_object(wm, workspace, ob);
+
GPU_drawobject_free(ob->derivedFinal);
WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
@@ -1471,8 +1147,8 @@ static int brush_colors_flip_exec(bContext *C, wmOperator *UNUSED(op))
{
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
- Brush *br;
Object *ob = CTX_data_active_object(C);
+ Brush *br;
if (!(ob && (ob->mode & OB_MODE_VERTEX_PAINT))) {
br = image_paint_brush(C);
}
@@ -1529,15 +1205,17 @@ void PAINT_OT_brush_colors_flip(wmOperatorType *ot)
void ED_imapaint_bucket_fill(struct bContext *C, float color[3], wmOperator *op)
{
+ wmWindowManager *wm = CTX_wm_manager(C);
SpaceImage *sima = CTX_wm_space_image(C);
Image *ima = sima->image;
- ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
- ED_image_undo_restore, ED_image_undo_free, NULL);
+ BKE_undosys_step_push_init_with_type(wm->undo_stack, C, op->type->name, BKE_UNDOSYS_TYPE_IMAGE);
+
+ ED_image_undo_push_begin(op->type->name);
paint_2d_bucket_fill(C, color, NULL, NULL, NULL);
- ED_undo_paint_push_end(UNDO_PAINT_IMAGE);
+ BKE_undosys_step_push(wm->undo_stack, C, op->type->name);
DEG_id_tag_update(&ima->id, 0);
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 2ce7c51b6b4..83a5a0d0b1b 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -1036,6 +1036,8 @@ static void paint_2d_do_making_brush(ImagePaintState *s,
ImBuf tmpbuf;
IMB_initImBuf(&tmpbuf, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, 0);
+ ListBase *undo_tiles = ED_image_undo_get_tiles();
+
for (int ty = tiley; ty <= tileh; ty++) {
for (int tx = tilex; tx <= tilew; tx++) {
/* retrieve original pixels + mask from undo buffer */
@@ -1044,9 +1046,9 @@ static void paint_2d_do_making_brush(ImagePaintState *s,
int origy = region->desty - ty * IMAPAINT_TILE_SIZE;
if (s->canvas->rect_float)
- tmpbuf.rect_float = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask, false);
+ tmpbuf.rect_float = image_undo_find_tile(undo_tiles, s->image, s->canvas, tx, ty, &mask, false);
else
- tmpbuf.rect = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask, false);
+ tmpbuf.rect = image_undo_find_tile(undo_tiles, s->image, s->canvas, tx, ty, &mask, false);
IMB_rectblend(s->canvas, &tmpbuf, frombuf, mask,
curveb, texmaskb, mask_max,
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 4a14e985827..c81a59b045f 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -1501,15 +1501,16 @@ static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty)
if (generate_tile) {
+ ListBase *undo_tiles = ED_image_undo_get_tiles();
volatile void *undorect;
if (tinf->masked) {
undorect = image_undo_push_tile(
- pjIma->ima, pjIma->ibuf, tinf->tmpibuf,
+ undo_tiles, pjIma->ima, pjIma->ibuf, tinf->tmpibuf,
tx, ty, &pjIma->maskRect[tile_index], &pjIma->valid[tile_index], true, false);
}
else {
undorect = image_undo_push_tile(
- pjIma->ima, pjIma->ibuf, tinf->tmpibuf,
+ undo_tiles, pjIma->ima, pjIma->ibuf, tinf->tmpibuf,
tx, ty, NULL, &pjIma->valid[tile_index], true, false);
}
@@ -2694,7 +2695,7 @@ static void project_paint_face_init(
int face_seam_flag;
if (threaded)
- BLI_lock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
+ BLI_thread_lock(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
face_seam_flag = ps->faceSeamFlags[tri_index];
@@ -2711,7 +2712,7 @@ static void project_paint_face_init(
if ((face_seam_flag & (PROJ_FACE_SEAM1 | PROJ_FACE_SEAM2 | PROJ_FACE_SEAM3)) == 0) {
if (threaded)
- BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
+ BLI_thread_unlock(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
}
else {
@@ -2737,7 +2738,7 @@ static void project_paint_face_init(
/* ps->faceSeamUVs cant be modified when threading, now this is done we can unlock */
if (threaded)
- BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
+ BLI_thread_unlock(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
vCoSS[0] = ps->screenCoords[lt_vtri[0]];
vCoSS[1] = ps->screenCoords[lt_vtri[1]];
@@ -4138,7 +4139,7 @@ static bool project_bucket_iter_next(
const int diameter = 2 * ps->brush_size;
if (ps->thread_tot > 1)
- BLI_lock_thread(LOCK_CUSTOM1);
+ BLI_thread_lock(LOCK_CUSTOM1);
//printf("%d %d\n", ps->context_bucket_x, ps->context_bucket_y);
@@ -4155,7 +4156,7 @@ static bool project_bucket_iter_next(
ps->context_bucket_x++;
if (ps->thread_tot > 1)
- BLI_unlock_thread(LOCK_CUSTOM1);
+ BLI_thread_unlock(LOCK_CUSTOM1);
return 1;
}
@@ -4164,7 +4165,7 @@ static bool project_bucket_iter_next(
}
if (ps->thread_tot > 1)
- BLI_unlock_thread(LOCK_CUSTOM1);
+ BLI_thread_unlock(LOCK_CUSTOM1);
return 0;
}
@@ -4883,7 +4884,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
}
if (ps->thread_tot > 1)
- BLI_init_threads(&threads, do_projectpaint_thread, ps->thread_tot);
+ BLI_threadpool_init(&threads, do_projectpaint_thread, ps->thread_tot);
pool = BKE_image_pool_new();
@@ -4913,11 +4914,11 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
handles[a].pool = pool;
if (ps->thread_tot > 1)
- BLI_insert_thread(&threads, &handles[a]);
+ BLI_threadpool_insert(&threads, &handles[a]);
}
if (ps->thread_tot > 1) /* wait for everything to be done */
- BLI_end_threads(&threads);
+ BLI_threadpool_end(&threads);
else
do_projectpaint_thread(&handles[0]);
@@ -5396,8 +5397,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING;
- ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
- ED_image_undo_restore, ED_image_undo_free, NULL);
+ ED_image_undo_push_begin(op->type->name);
/* allocate and initialize spatial data structures */
project_paint_begin(C, &ps, false, 0);
@@ -5459,6 +5459,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
+ struct RenderEngineType *engine_type = CTX_data_engine_type(C);
EvaluationContext eval_ctx;
ToolSettings *settings = scene->toolsettings;
int w = settings->imapaint.screen_grab_size[0];
@@ -5476,9 +5477,10 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
if (h > maxsize) h = maxsize;
ibuf = ED_view3d_draw_offscreen_imbuf(
- &eval_ctx, scene, view_layer, CTX_wm_view3d(C), CTX_wm_region(C),
+ &eval_ctx, scene, view_layer, engine_type,
+ CTX_wm_view3d(C), CTX_wm_region(C),
w, h, IB_rect, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL,
- NULL, NULL, err_out);
+ NULL, err_out);
if (!ibuf) {
/* Mostly happens when OpenGL offscreen buffer was failed to create, */
/* but could be other reasons. Should be handled in the future. nazgul */
@@ -5943,9 +5945,9 @@ static int add_simple_uvs_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
- if (!ob || ob->type != OB_MESH || ob->mode != OB_MODE_TEXTURE_PAINT)
+ if (!ob || ob->type != OB_MESH || ob->mode != OB_MODE_TEXTURE_PAINT) {
return false;
-
+ }
return true;
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_undo.c b/source/blender/editors/sculpt_paint/paint_image_undo.c
new file mode 100644
index 00000000000..ade775d14e6
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_image_undo.c
@@ -0,0 +1,535 @@
+/*
+ * ***** 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.
+ *
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/sculpt_paint/paint_image_undo.c
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_threads.h"
+
+#include "DNA_image_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_workspace_types.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "BKE_context.h"
+#include "BKE_image.h"
+#include "BKE_main.h"
+#include "BKE_undo_system.h"
+
+#include "DEG_depsgraph.h"
+
+#include "ED_paint.h"
+#include "ED_undo.h"
+
+#include "GPU_draw.h"
+
+#include "paint_intern.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Undo Conversion
+ * \{ */
+
+typedef struct UndoImageTile {
+ struct UndoImageTile *next, *prev;
+
+ char ibufname[IMB_FILENAME_SIZE];
+
+ union {
+ float *fp;
+ unsigned int *uint;
+ void *pt;
+ } rect;
+
+ unsigned short *mask;
+
+ int x, y;
+
+ Image *ima;
+ short source, use_float;
+ char gen_type;
+ bool valid;
+
+ size_t undo_size;
+} UndoImageTile;
+
+/* this is a static resource for non-globality,
+ * Maybe it should be exposed as part of the
+ * paint operation, but for now just give a public interface */
+static SpinLock undolock;
+
+void image_undo_init_locks(void)
+{
+ BLI_spin_init(&undolock);
+}
+
+void image_undo_end_locks(void)
+{
+ BLI_spin_end(&undolock);
+}
+
+/* UNDO */
+typedef enum {
+ COPY = 0,
+ RESTORE = 1,
+ RESTORE_COPY = 2
+} CopyMode;
+
+static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, CopyMode mode)
+{
+ if (mode == COPY) {
+ /* copy or swap contents of tile->rect and region in ibuf->rect */
+ IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
+ tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+
+ if (ibuf->rect_float) {
+ SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+ }
+ else {
+ SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
+ }
+ }
+ else {
+ if (mode == RESTORE_COPY) {
+ IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
+ tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+ }
+ /* swap to the tmpbuf for easy copying */
+ if (ibuf->rect_float) {
+ SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+ }
+ else {
+ SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
+ }
+
+ IMB_rectcpy(ibuf, tmpibuf, tile->x * IMAPAINT_TILE_SIZE,
+ tile->y * IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+
+ if (mode == RESTORE) {
+ if (ibuf->rect_float) {
+ SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+ }
+ else {
+ SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
+ }
+ }
+ }
+}
+
+void *image_undo_find_tile(
+ ListBase *undo_tiles,
+ Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask, bool validate)
+{
+ UndoImageTile *tile;
+ short use_float = ibuf->rect_float ? 1 : 0;
+
+ for (tile = undo_tiles->first; tile; tile = tile->next) {
+ if (tile->x == x_tile && tile->y == y_tile && ima->gen_type == tile->gen_type && ima->source == tile->source) {
+ if (tile->use_float == use_float) {
+ if (STREQ(tile->ibufname, ibuf->name)) {
+ if (mask) {
+ /* allocate mask if requested */
+ if (!tile->mask) {
+ tile->mask = MEM_callocN(sizeof(unsigned short) * IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE,
+ "UndoImageTile.mask");
+ }
+
+ *mask = tile->mask;
+ }
+ if (validate) {
+ tile->valid = true;
+ }
+ return tile->rect.pt;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+void *image_undo_push_tile(
+ ListBase *undo_tiles,
+ Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile,
+ unsigned short **mask, bool **valid, bool proj, bool find_prev)
+{
+ UndoImageTile *tile;
+ int allocsize;
+ short use_float = ibuf->rect_float ? 1 : 0;
+ void *data;
+
+ /* check if tile is already pushed */
+
+ /* in projective painting we keep accounting of tiles, so if we need one pushed, just push! */
+ if (find_prev) {
+ data = image_undo_find_tile(undo_tiles, ima, ibuf, x_tile, y_tile, mask, true);
+ if (data) {
+ return data;
+ }
+ }
+
+ if (*tmpibuf == NULL) {
+ *tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect);
+ }
+
+ tile = MEM_callocN(sizeof(UndoImageTile), "UndoImageTile");
+ tile->x = x_tile;
+ tile->y = y_tile;
+
+ /* add mask explicitly here */
+ if (mask) {
+ *mask = tile->mask = MEM_callocN(sizeof(unsigned short) * IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE,
+ "UndoImageTile.mask");
+ }
+ allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
+ allocsize *= (ibuf->rect_float) ? sizeof(float) : sizeof(char);
+ tile->rect.pt = MEM_mapallocN(allocsize, "UndeImageTile.rect");
+
+ BLI_strncpy(tile->ibufname, ibuf->name, sizeof(tile->ibufname));
+
+ tile->gen_type = ima->gen_type;
+ tile->source = ima->source;
+ tile->use_float = use_float;
+ tile->valid = true;
+ tile->ima = ima;
+
+ if (valid) {
+ *valid = &tile->valid;
+ }
+ undo_copy_tile(tile, *tmpibuf, ibuf, COPY);
+
+ if (proj) {
+ BLI_spin_lock(&undolock);
+ }
+ BLI_addtail(undo_tiles, tile);
+
+ if (proj) {
+ BLI_spin_unlock(&undolock);
+ }
+ return tile->rect.pt;
+}
+
+void image_undo_remove_masks(void)
+{
+ ListBase *undo_tiles = ED_image_undo_get_tiles();
+ UndoImageTile *tile;
+
+ for (tile = undo_tiles->first; tile; tile = tile->next) {
+ if (tile->mask) {
+ MEM_freeN(tile->mask);
+ tile->mask = NULL;
+ }
+ }
+}
+
+static void image_undo_restore_runtime(ListBase *lb)
+{
+ ImBuf *ibuf, *tmpibuf;
+ UndoImageTile *tile;
+
+ tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32,
+ IB_rectfloat | IB_rect);
+
+ for (tile = lb->first; tile; tile = tile->next) {
+ Image *ima = tile->ima;
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+
+ undo_copy_tile(tile, tmpibuf, ibuf, RESTORE);
+
+ GPU_free_image(ima); /* force OpenGL reload (maybe partial update will operate better?) */
+ if (ibuf->rect_float) {
+ ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
+ }
+ if (ibuf->mipmap[0]) {
+ ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */
+ }
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+
+ IMB_freeImBuf(tmpibuf);
+}
+
+static void image_undo_restore_list(ListBase *lb, struct UndoIDPtrMap *id_map)
+{
+ ImBuf *tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect);
+
+ /* Store last found image. */
+ ID *image_prev[2] = {NULL};
+
+ for (UndoImageTile *tile = lb->first; tile; tile = tile->next) {
+ short use_float;
+
+ Image *ima = (Image *)BKE_undosys_ID_map_lookup_with_prev(id_map, &tile->ima->id, image_prev);
+
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+
+ if (ima && ibuf && !STREQ(tile->ibufname, ibuf->name)) {
+ /* current ImBuf filename was changed, probably current frame
+ * was changed when painting on image sequence, rather than storing
+ * full image user (which isn't so obvious, btw) try to find ImBuf with
+ * matched file name in list of already loaded images */
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+
+ ibuf = BKE_image_get_ibuf_with_name(ima, tile->ibufname);
+ }
+
+ if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ continue;
+ }
+
+ if (ima->gen_type != tile->gen_type || ima->source != tile->source) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ continue;
+ }
+
+ use_float = ibuf->rect_float ? 1 : 0;
+
+ if (use_float != tile->use_float) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ continue;
+ }
+
+ undo_copy_tile(tile, tmpibuf, ibuf, RESTORE_COPY);
+
+ GPU_free_image(ima); /* force OpenGL reload */
+ if (ibuf->rect_float) {
+ ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
+ }
+ if (ibuf->mipmap[0]) {
+ ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */
+ }
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+
+ DEG_id_tag_update(&ima->id, 0);
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+
+ IMB_freeImBuf(tmpibuf);
+}
+
+static void image_undo_free_list(ListBase *lb)
+{
+ UndoImageTile *tile;
+
+ for (tile = lb->first; tile; tile = tile->next) {
+ MEM_freeN(tile->rect.pt);
+ }
+}
+
+void ED_image_undo_push_begin(const char *name)
+{
+ UndoStack *ustack = ED_undo_stack_get();
+ bContext *C = NULL; /* special case, we never read from this. */
+ BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_IMAGE);
+}
+
+void ED_image_undo_push_end(void)
+{
+ UndoStack *ustack = ED_undo_stack_get();
+ BKE_undosys_step_push(ustack, NULL, NULL);
+}
+
+static void image_undo_invalidate(void)
+{
+ UndoImageTile *tile;
+ ListBase *lb = ED_image_undo_get_tiles();
+
+ for (tile = lb->first; tile; tile = tile->next) {
+ tile->valid = false;
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Implements ED Undo System
+ * \{ */
+
+typedef struct ImageUndoStep {
+ UndoStep step;
+ ListBase tiles;
+
+ /* Use for all ID lookups (can be NULL). */
+ struct UndoIDPtrMap *id_map;
+} ImageUndoStep;
+
+static void image_undosys_step_encode_store_ids(ImageUndoStep *us)
+{
+ us->id_map = BKE_undosys_ID_map_create();
+
+ ID *image_prev = NULL;
+ for (UndoImageTile *tile = us->tiles.first; tile; tile = tile->next) {
+ BKE_undosys_ID_map_add_with_prev(us->id_map, &tile->ima->id, &image_prev);
+ }
+}
+
+/* Restore at runtime. */
+#if 0
+static void paint_undosys_step_decode_restore_ids(ImageUndoStep *us)
+{
+ ID *image_prev[2] = {NULL};
+ for (UndoImageTile *tile = us->tiles.first; tile; tile = tile->next) {
+ tile->ima = (Image *)BKE_undosys_ID_map_lookup_with_prev(us->id_map, &tile->ima->id, image_prev);
+ }
+}
+#endif
+
+static bool image_undosys_poll(bContext *C)
+{
+ Object *obact = CTX_data_active_object(C);
+
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa && (sa->spacetype == SPACE_IMAGE)) {
+ SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
+ if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) || (sima->mode == SI_MODE_PAINT)) {
+ return true;
+ }
+ }
+ else if (sa && (sa->spacetype == SPACE_VIEW3D)) {
+ if (obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void image_undosys_step_encode_init(struct bContext *UNUSED(C), UndoStep *us_p)
+{
+ ImageUndoStep *us = (ImageUndoStep *)us_p;
+ /* dummy, memory is cleared anyway. */
+ BLI_listbase_clear(&us->tiles);
+}
+
+static bool image_undosys_step_encode(struct bContext *UNUSED(C), UndoStep *us_p)
+{
+ /* dummy, encoding is done along the way by adding tiles
+ * to the current 'ImageUndoStep' added by encode_init. */
+ ImageUndoStep *us = (ImageUndoStep *)us_p;
+
+ BLI_assert(us->step.data_size == 0);
+
+ int allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
+
+
+ /* first dispose of invalid tiles (may happen due to drag dot for instance) */
+ for (UndoImageTile *tile = us->tiles.first; tile;) {
+ if (!tile->valid) {
+ UndoImageTile *tmp_tile = tile->next;
+ MEM_freeN(tile->rect.pt);
+ BLI_freelinkN(&us->tiles, tile);
+ tile = tmp_tile;
+ }
+ else {
+ us->step.data_size += allocsize * ((tile->use_float) ? sizeof(float) : sizeof(char));
+ tile = tile->next;
+ }
+ }
+
+ image_undosys_step_encode_store_ids(us);
+
+ return true;
+}
+
+static void image_undosys_step_decode(struct bContext *UNUSED(C), UndoStep *us_p, int UNUSED(dir))
+{
+ ImageUndoStep *us = (ImageUndoStep *)us_p;
+#if 0
+ paint_undosys_step_decode_restore_ids(us);
+#endif
+ image_undo_restore_list(&us->tiles, us->id_map);
+}
+
+static void image_undosys_step_free(UndoStep *us_p)
+{
+ ImageUndoStep *us = (ImageUndoStep *)us_p;
+ image_undo_free_list(&us->tiles);
+ BKE_undosys_ID_map_destroy(us->id_map);
+}
+
+static void image_undosys_foreach_ID_ref(
+ UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+{
+ ImageUndoStep *us = (ImageUndoStep *)us_p;
+ if (us->id_map != NULL) {
+ BKE_undosys_ID_map_foreach_ID_ref(us->id_map, foreach_ID_ref_fn, user_data);
+ }
+}
+
+/* Export for ED_undo_sys. */
+void ED_image_undosys_type(UndoType *ut)
+{
+ ut->name = "Image";
+ ut->poll = image_undosys_poll;
+ ut->step_encode_init = image_undosys_step_encode_init;
+ ut->step_encode = image_undosys_step_encode;
+ ut->step_decode = image_undosys_step_decode;
+ ut->step_free = image_undosys_step_free;
+
+ ut->step_foreach_ID_ref = image_undosys_foreach_ID_ref;
+
+ ut->mode = BKE_UNDOTYPE_MODE_ACCUMULATE;
+ ut->use_context = true;
+
+ ut->step_size = sizeof(ImageUndoStep);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/** \name Utilities
+ * \{ */
+
+ListBase *ED_image_undosys_step_get_tiles(UndoStep *us_p)
+{
+ ImageUndoStep *us = (ImageUndoStep *)us_p;
+ return &us->tiles;
+}
+
+ListBase *ED_image_undo_get_tiles(void)
+{
+ UndoStack *ustack = ED_undo_stack_get();
+ UndoStep *us = BKE_undosys_stack_init_or_active_with_type(ustack, BKE_UNDOSYS_TYPE_IMAGE);
+ return ED_image_undosys_step_get_tiles(us);
+}
+
+/* restore painting image to previous state. Used for anchored and drag-dot style brushes*/
+void ED_image_undo_restore(UndoStep *us)
+{
+ ListBase *lb = ED_image_undosys_step_get_tiles(us);
+ image_undo_restore_runtime(lb);
+ image_undo_invalidate();
+}
+
+/** \} */
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 28d9dfe13b0..e22b996c6e5 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -43,6 +43,7 @@ struct MTex;
struct Object;
struct PaintStroke;
struct Paint;
+struct PaintCurve;
struct PointerRNA;
struct rcti;
struct Scene;
@@ -54,6 +55,7 @@ struct wmOperator;
struct wmOperatorType;
struct wmWindowManager;
struct DMCoNo;
+struct UndoStep;
enum ePaintMode;
/* paint_stroke.c */
@@ -176,12 +178,6 @@ typedef struct ImagePaintPartialRedraw {
#define IMAPAINT_TILE_NUMBER(size) (((size) + IMAPAINT_TILE_SIZE - 1) >> IMAPAINT_TILE_BITS)
int image_texture_paint_poll(struct bContext *C);
-void *image_undo_find_tile(struct Image *ima, struct ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask, bool validate);
-void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **, bool **valid, bool proj, bool find_prev);
-void image_undo_remove_masks(void);
-void image_undo_init_locks(void);
-void image_undo_end_locks(void);
-
void imapaint_image_update(struct SpaceImage *sima, struct Image *image, struct ImBuf *ibuf, short texpaint);
struct ImagePaintPartialRedraw *get_imapaintpartial(void);
void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr);
@@ -190,15 +186,25 @@ int get_imapaint_zoom(struct bContext *C, float *zoomx, float *zoomy);
void *paint_2d_new_stroke(struct bContext *, struct wmOperator *, int mode);
void paint_2d_redraw(const struct bContext *C, void *ps, bool final);
void paint_2d_stroke_done(void *ps);
-void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], const bool eraser, float pressure, float distance, float size);
-void paint_2d_bucket_fill(const struct bContext *C, const float color[3], struct Brush *br, const float mouse_init[2], void *ps);
-void paint_2d_gradient_fill(const struct bContext *C, struct Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps);
-void *paint_proj_new_stroke(struct bContext *C, struct Object *ob, const float mouse[2], int mode);
-void paint_proj_stroke(const struct bContext *C, void *ps, const float prevmval_i[2], const float mval_i[2], const bool eraser, float pressure, float distance, float size);
+void paint_2d_stroke(
+ void *ps, const float prev_mval[2], const float mval[2],
+ const bool eraser, float pressure, float distance, float size);
+void paint_2d_bucket_fill(
+ const struct bContext *C, const float color[3], struct Brush *br, const float mouse_init[2], void *ps);
+void paint_2d_gradient_fill(
+ const struct bContext *C, struct Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps);
+void *paint_proj_new_stroke(
+ struct bContext *C, struct Object *ob, const float mouse[2], int mode);
+void paint_proj_stroke(
+ const struct bContext *C, void *ps, const float prevmval_i[2], const float mval_i[2],
+ const bool eraser, float pressure, float distance, float size);
void paint_proj_redraw(const struct bContext *C, void *pps, bool final);
void paint_proj_stroke_done(void *ps);
-void paint_brush_color_get(struct Scene *scene, struct Brush *br, bool color_correction, bool invert, float distance, float pressure, float color[3], struct ColorManagedDisplay *display);
+void paint_brush_color_get(
+ struct Scene *scene, struct Brush *br,
+ bool color_correction, bool invert, float distance, float pressure, float color[3],
+ struct ColorManagedDisplay *display);
bool paint_use_opacity_masking(struct Brush *brush);
void paint_brush_init_tex(struct Brush *brush);
void paint_brush_exit_tex(struct Brush *brush);
@@ -214,7 +220,23 @@ void PAINT_OT_delete_texture_paint_slot(struct wmOperatorType *ot);
void PAINT_OT_image_paint(struct wmOperatorType *ot);
void PAINT_OT_add_simple_uvs(struct wmOperatorType *ot);
-/* uv sculpting */
+/* paint_image_undo.c */
+void *image_undo_find_tile(
+ ListBase *undo_tiles,
+ struct Image *ima, struct ImBuf *ibuf, int x_tile, int y_tile,
+ unsigned short **mask, bool validate);
+void *image_undo_push_tile(
+ ListBase *undo_tiles,
+ struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile,
+ unsigned short **, bool **valid, bool proj, bool find_prev);
+void image_undo_remove_masks(void);
+void image_undo_init_locks(void);
+void image_undo_end_locks(void);
+
+struct ListBase *ED_image_undosys_step_get_tiles(struct UndoStep *us_p);
+struct ListBase *ED_image_undo_get_tiles(void);
+
+/* sculpt_uv.c */
int uv_sculpt_poll(struct bContext *C);
int uv_sculpt_keymap_poll(struct bContext *C);
@@ -287,10 +309,6 @@ typedef enum {
void set_brush_rc_props(struct PointerRNA *ptr, const char *paint, const char *prop, const char *secondary_prop,
RCFlags flags);
-/* paint_undo.c */
-struct ListBase *undo_paint_push_get_list(int type);
-void undo_paint_push_count_alloc(int type, int size);
-
/* paint_hide.c */
typedef enum {
@@ -327,6 +345,9 @@ void PAINTCURVE_OT_slide(struct wmOperatorType *ot);
void PAINTCURVE_OT_draw(struct wmOperatorType *ot);
void PAINTCURVE_OT_cursor(struct wmOperatorType *ot);
+/* paint_curve_undo.c */
+void ED_paintcurve_undo_push(struct bContext *C, struct wmOperator *op, struct PaintCurve *pc);
+
/* image painting blur kernel */
typedef struct {
float *wdata; /* actual kernel */
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index ff261a808da..162c067166c 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -39,7 +39,7 @@
#include "BLI_math_matrix.h"
#include "BLI_math_geom.h"
#include "BLI_utildefines.h"
-#include "BLI_lasso.h"
+#include "BLI_lasso_2d.h"
#include "BLI_task.h"
#include "BKE_pbvh.h"
@@ -171,7 +171,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
if (multires)
multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
- sculpt_undo_push_end(C);
+ sculpt_undo_push_end();
if (nodes)
MEM_freeN(nodes);
@@ -327,7 +327,7 @@ int ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *r
if (multires)
multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
- sculpt_undo_push_end(C);
+ sculpt_undo_push_end();
ED_region_tag_redraw(ar);
@@ -449,7 +449,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
/* Calculations of individual vertices are done in 2D screen space to diminish the amount of
* calculations done. Bounding box PBVH collision is not computed against enclosing rectangle
* of lasso */
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
/* lasso data calculations */
data.vc = &vc;
@@ -514,7 +514,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
if (multires)
multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
- sculpt_undo_push_end(C);
+ sculpt_undo_push_end();
ED_region_tag_redraw(vc.ar);
MEM_freeN((void *)mcords);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 3982c9a3c30..861015375cb 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -698,7 +698,7 @@ PaintStroke *paint_stroke_new(bContext *C,
Brush *br = stroke->brush = BKE_paint_brush(p);
float zoomx, zoomy;
- view3d_set_viewcontext(C, &stroke->vc);
+ ED_view3d_viewcontext_init(C, &stroke->vc);
stroke->get_location = get_location;
stroke->test_start = test_start;
diff --git a/source/blender/editors/sculpt_paint/paint_undo.c b/source/blender/editors/sculpt_paint/paint_undo.c
deleted file mode 100644
index 27d3f6648a2..00000000000
--- a/source/blender/editors/sculpt_paint/paint_undo.c
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/sculpt_paint/paint_undo.c
- * \ingroup edsculpt
- * \brief Undo system for painting and sculpting.
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_listbase.h"
-#include "BLI_utildefines.h"
-#include "BLI_string.h"
-
-#include "DNA_userdef_types.h"
-
-#include "BKE_blender_undo.h"
-#include "BKE_context.h"
-#include "BKE_global.h"
-
-#include "ED_paint.h"
-
-#include "paint_intern.h"
-
-typedef struct UndoElem {
- struct UndoElem *next, *prev;
- char name[BKE_UNDO_STR_MAX];
- uintptr_t undosize;
-
- ListBase elems;
-
- UndoRestoreCb restore;
- UndoFreeCb free;
- UndoCleanupCb cleanup;
-} UndoElem;
-
-typedef struct UndoStack {
- int type;
- ListBase elems;
- UndoElem *current;
-} UndoStack;
-
-static UndoStack ImageUndoStack = {UNDO_PAINT_IMAGE, {NULL, NULL}, NULL};
-static UndoStack MeshUndoStack = {UNDO_PAINT_MESH, {NULL, NULL}, NULL};
-
-/* Generic */
-
-static void undo_restore(bContext *C, UndoStack *UNUSED(stack), UndoElem *uel)
-{
- if (uel && uel->restore)
- uel->restore(C, &uel->elems);
-}
-
-static void undo_elem_free(UndoStack *UNUSED(stack), UndoElem *uel)
-{
- if (uel && uel->free) {
- uel->free(&uel->elems);
- BLI_freelistN(&uel->elems);
- }
-}
-
-static void undo_stack_push_begin(UndoStack *stack, const char *name, UndoRestoreCb restore, UndoFreeCb free, UndoCleanupCb cleanup)
-{
- UndoElem *uel;
- int nr;
-
- /* Undo push is split up in begin and end, the reason is that as painting
- * happens more tiles/nodes are added to the list, and at the very end we
- * know how much memory the undo used to remove old undo elements */
-
- /* remove all undos after (also when stack->current==NULL) */
- while (stack->elems.last != stack->current) {
- uel = stack->elems.last;
- undo_elem_free(stack, uel);
- BLI_freelinkN(&stack->elems, uel);
- }
-
- /* make new */
- stack->current = uel = MEM_callocN(sizeof(UndoElem), "undo file");
- uel->restore = restore;
- uel->free = free;
- uel->cleanup = cleanup;
- BLI_addtail(&stack->elems, uel);
-
- /* name can be a dynamic string */
- BLI_strncpy(uel->name, name, sizeof(uel->name));
-
- /* limit amount to the maximum amount*/
- nr = 0;
- uel = stack->elems.last;
- while (uel) {
- nr++;
- if (nr == U.undosteps) break;
- uel = uel->prev;
- }
- if (uel) {
- while (stack->elems.first != uel) {
- UndoElem *first = stack->elems.first;
- undo_elem_free(stack, first);
- BLI_freelinkN(&stack->elems, first);
- }
- }
-}
-
-static void undo_stack_push_end(UndoStack *stack)
-{
- UndoElem *uel;
- uintptr_t totmem, maxmem;
- int totundo = 0;
-
- /* first limit to undo steps */
- uel = stack->elems.last;
-
- while (uel) {
- totundo++;
- if (totundo > U.undosteps) break;
- uel = uel->prev;
- }
-
- if (uel) {
- UndoElem *first;
-
- /* in case the undo steps are zero, the current pointer will be invalid */
- if (uel == stack->current)
- stack->current = NULL;
-
- do {
- first = stack->elems.first;
- undo_elem_free(stack, first);
- BLI_freelinkN(&stack->elems, first);
- } while (first != uel);
- }
-
- if (U.undomemory != 0) {
- /* limit to maximum memory (afterwards, we can't know in advance) */
- totmem = 0;
- maxmem = ((uintptr_t)U.undomemory) * 1024 * 1024;
-
- uel = stack->elems.last;
- while (uel) {
- totmem += uel->undosize;
- if (totmem > maxmem) break;
- uel = uel->prev;
- }
-
- if (uel) {
- while (stack->elems.first != uel) {
- UndoElem *first = stack->elems.first;
- undo_elem_free(stack, first);
- BLI_freelinkN(&stack->elems, first);
- }
- }
- }
-}
-
-static void undo_stack_cleanup(UndoStack *stack, bContext *C)
-{
- UndoElem *uel = stack->elems.first;
- bool stack_reset = false;
-
- while (uel) {
- if (uel->cleanup && uel->cleanup(C, &uel->elems)) {
- UndoElem *uel_tmp = uel->next;
- if (stack->current == uel) {
- stack->current = NULL;
- stack_reset = true;
- }
- undo_elem_free(stack, uel);
- BLI_freelinkN(&stack->elems, uel);
- uel = uel_tmp;
- }
- else
- uel = uel->next;
- }
- if (stack_reset) {
- stack->current = stack->elems.last;
- }
-
-}
-
-static int undo_stack_step(bContext *C, UndoStack *stack, int step, const char *name)
-{
- UndoElem *undo;
-
- /* first cleanup any old undo steps that may belong to invalid data */
- undo_stack_cleanup(stack, C);
-
- if (step == 1) {
- if (stack->current == NULL) {
- /* pass */
- }
- else {
- if (!name || STREQ(stack->current->name, name)) {
- if (G.debug & G_DEBUG_WM) {
- printf("%s: undo '%s'\n", __func__, stack->current->name);
- }
- undo_restore(C, stack, stack->current);
- stack->current = stack->current->prev;
- return 1;
- }
- }
- }
- else if (step == -1) {
- if ((stack->current != NULL && stack->current->next == NULL) || BLI_listbase_is_empty(&stack->elems)) {
- /* pass */
- }
- else {
- if (!name || STREQ(stack->current->name, name)) {
- undo = (stack->current && stack->current->next) ? stack->current->next : stack->elems.first;
- undo_restore(C, stack, undo);
- stack->current = undo;
- if (G.debug & G_DEBUG_WM) {
- printf("%s: redo %s\n", __func__, undo->name);
- }
- return 1;
- }
- }
- }
-
- return 0;
-}
-
-static void undo_stack_free(UndoStack *stack)
-{
- UndoElem *uel;
-
- for (uel = stack->elems.first; uel; uel = uel->next)
- undo_elem_free(stack, uel);
-
- BLI_freelistN(&stack->elems);
- stack->current = NULL;
-}
-
-/* Exported Functions */
-
-void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free, UndoCleanupCb cleanup)
-{
- if (type == UNDO_PAINT_IMAGE)
- undo_stack_push_begin(&ImageUndoStack, name, restore, free, cleanup);
- else if (type == UNDO_PAINT_MESH)
- undo_stack_push_begin(&MeshUndoStack, name, restore, free, cleanup);
-}
-
-ListBase *undo_paint_push_get_list(int type)
-{
- if (type == UNDO_PAINT_IMAGE) {
- if (ImageUndoStack.current) {
- return &ImageUndoStack.current->elems;
- }
- }
- else if (type == UNDO_PAINT_MESH) {
- if (MeshUndoStack.current) {
- return &MeshUndoStack.current->elems;
- }
- }
-
- return NULL;
-}
-
-void undo_paint_push_count_alloc(int type, int size)
-{
- if (type == UNDO_PAINT_IMAGE)
- ImageUndoStack.current->undosize += size;
- else if (type == UNDO_PAINT_MESH)
- MeshUndoStack.current->undosize += size;
-}
-
-void ED_undo_paint_push_end(int type)
-{
- if (type == UNDO_PAINT_IMAGE)
- undo_stack_push_end(&ImageUndoStack);
- else if (type == UNDO_PAINT_MESH)
- undo_stack_push_end(&MeshUndoStack);
-}
-
-int ED_undo_paint_step(bContext *C, int type, int step, const char *name)
-{
- if (type == UNDO_PAINT_IMAGE)
- return undo_stack_step(C, &ImageUndoStack, step, name);
- else if (type == UNDO_PAINT_MESH)
- return undo_stack_step(C, &MeshUndoStack, step, name);
-
- return 0;
-}
-
-static void undo_step_num(bContext *C, UndoStack *stack, int step)
-{
- UndoElem *uel;
- int a = 0;
- int curnum = BLI_findindex(&stack->elems, stack->current);
-
- for (uel = stack->elems.first; uel; uel = uel->next, a++) {
- if (a == step) break;
- }
-
- if (curnum > a) {
- while (a++ != curnum)
- undo_stack_step(C, stack, 1, NULL);
- }
- else if (curnum < a) {
- while (a-- != curnum)
- undo_stack_step(C, stack, -1, NULL);
- }
-}
-
-void ED_undo_paint_step_num(bContext *C, int type, int step)
-{
- if (type == UNDO_PAINT_IMAGE)
- undo_step_num(C, &ImageUndoStack, step);
- else if (type == UNDO_PAINT_MESH)
- undo_step_num(C, &MeshUndoStack, step);
-}
-
-static char *undo_stack_get_name(UndoStack *stack, int nr, bool *r_active)
-{
- UndoElem *uel;
-
- if (r_active) *r_active = false;
-
- uel = BLI_findlink(&stack->elems, nr);
- if (uel) {
- if (r_active && (uel == stack->current)) {
- *r_active = true;
- }
- return uel->name;
- }
-
- return NULL;
-}
-
-const char *ED_undo_paint_get_name(bContext *C, int type, int nr, bool *r_active)
-{
-
- if (type == UNDO_PAINT_IMAGE) {
- undo_stack_cleanup(&ImageUndoStack, C);
- return undo_stack_get_name(&ImageUndoStack, nr, r_active);
- }
- else if (type == UNDO_PAINT_MESH) {
- undo_stack_cleanup(&MeshUndoStack, C);
- return undo_stack_get_name(&MeshUndoStack, nr, r_active);
- }
- return NULL;
-}
-
-bool ED_undo_paint_empty(int type)
-{
- UndoStack *stack;
-
- if (type == UNDO_PAINT_IMAGE)
- stack = &ImageUndoStack;
- else if (type == UNDO_PAINT_MESH)
- stack = &MeshUndoStack;
- else
- return true;
-
- if (stack->current == NULL) {
- return true;
- }
-
- return false;
-}
-
-bool ED_undo_paint_is_valid(int type, const char *name)
-{
- UndoStack *stack;
-
- if (type == UNDO_PAINT_IMAGE)
- stack = &ImageUndoStack;
- else if (type == UNDO_PAINT_MESH)
- stack = &MeshUndoStack;
- else
- return 0;
-
- if (stack->current == NULL) {
- /* pass */
- }
- else {
- if (name && STREQ(stack->current->name, name))
- return 1;
- else
- return stack->elems.first != stack->elems.last;
- }
- return 0;
-}
-
-void ED_undo_paint_free(void)
-{
- undo_stack_free(&ImageUndoStack);
- undo_stack_free(&MeshUndoStack);
-}
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 1ec1e052d43..0f22973c45d 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -468,7 +468,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
unsigned int totpoly = me->totpoly;
if (dm->getLoopDataArray(dm, CD_MLOOPUV)) {
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
view3d_operator_needs_opengl(C);
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 0c1df71b1aa..12fe55fb956 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -55,6 +55,8 @@
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_deform.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_object_deform.h"
@@ -940,6 +942,9 @@ static void do_weight_paint_vertex(
/* Toggle operator for turning vertex paint mode on or off (copied from sculpt.c) */
static void vertex_paint_init_session(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
+ /* Create persistent sculpt mode data */
+ BKE_sculpt_toolsettings_data_ensure(scene);
+
if (ob->sculpt == NULL) {
ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
BKE_sculpt_update_mesh_elements(eval_ctx, scene, scene->toolsettings->sculpt, ob, 0, false);
@@ -1024,78 +1029,193 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob)
}
-/* *************** set wpaint operator ****************** */
+/* -------------------------------------------------------------------- */
+/** \name Enter Vertex/Weight Paint Mode
+ * \{ */
-/**
- * \note Keep in sync with #vpaint_mode_toggle_exec
- */
-static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
+static void ed_vwpaintmode_enter_generic(
+ const EvaluationContext *eval_ctx, wmWindowManager *wm, Scene *scene,
+ Object *ob, const eObjectMode mode_flag)
{
- Object *ob = CTX_data_active_object(C);
- const int mode_flag = OB_MODE_WEIGHT_PAINT;
- const bool is_mode_set = (ob->mode & mode_flag) != 0;
- Scene *scene = CTX_data_scene(C);
- VPaint *wp = scene->toolsettings->wpaint;
- Mesh *me;
+ ob->mode |= mode_flag;
+ Mesh *me = BKE_mesh_from_object(ob);
- if (!is_mode_set) {
- if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
- return OPERATOR_CANCELLED;
- }
- }
+ if (mode_flag == OB_MODE_VERTEX_PAINT) {
+ const ePaintMode paint_mode = ePaintVertex;
+ ED_mesh_color_ensure(me, NULL);
- me = BKE_mesh_from_object(ob);
+ if (scene->toolsettings->vpaint == NULL) {
+ scene->toolsettings->vpaint = new_vpaint();
+ }
- if (ob->mode & mode_flag) {
- ob->mode &= ~mode_flag;
+ Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
+ paint_cursor_start_explicit(paint, wm, vertex_paint_poll);
+ BKE_paint_init(scene, paint_mode, PAINT_CURSOR_VERTEX_PAINT);
+ }
+ else if (mode_flag == OB_MODE_WEIGHT_PAINT) {
+ const ePaintMode paint_mode = ePaintWeight;
- if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
- BKE_mesh_flush_select_from_verts(me);
- }
- else if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
- BKE_mesh_flush_select_from_polys(me);
+ if (scene->toolsettings->wpaint == NULL) {
+ scene->toolsettings->wpaint = new_vpaint();
}
+ Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
+ paint_cursor_start_explicit(paint, wm, weight_paint_poll);
+ BKE_paint_init(scene, paint_mode, PAINT_CURSOR_WEIGHT_PAINT);
+
/* weight paint specific */
- ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
- ED_mesh_mirror_topo_table(NULL, NULL, 'e');
+ ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 's');
+ ED_vgroup_sync_from_pose(ob);
+ }
+ else {
+ BLI_assert(0);
+ }
- /* If the cache is not released by a cancel or a done, free it now. */
+ /* Create vertex/weight paint mode session data */
+ if (ob->sculpt) {
if (ob->sculpt->cache) {
sculpt_cache_free(ob->sculpt->cache);
ob->sculpt->cache = NULL;
}
-
BKE_sculptsession_free(ob);
+ }
- paint_cursor_delete_textures();
+ vertex_paint_init_session(eval_ctx, scene, ob);
+}
+
+void ED_object_vpaintmode_enter_ex(
+ const EvaluationContext *eval_ctx, wmWindowManager *wm,
+ Scene *scene, Object *ob)
+{
+ ed_vwpaintmode_enter_generic(
+ eval_ctx, wm, scene, ob, OB_MODE_VERTEX_PAINT);
+}
+void ED_object_vpaintmode_enter(struct bContext *C)
+{
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ ED_object_vpaintmode_enter_ex(&eval_ctx, wm, scene, ob);
+}
+
+void ED_object_wpaintmode_enter_ex(
+ const EvaluationContext *eval_ctx, wmWindowManager *wm,
+ Scene *scene, Object *ob)
+{
+ ed_vwpaintmode_enter_generic(
+ eval_ctx, wm, scene, ob, OB_MODE_WEIGHT_PAINT);
+}
+void ED_object_wpaintmode_enter(struct bContext *C)
+{
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ ED_object_wpaintmode_enter_ex(&eval_ctx, wm, scene, ob);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Exit Vertex/Weight Paint Mode
+ * \{ */
+
+static void ed_vwpaintmode_exit_generic(
+ Object *ob, const eObjectMode mode_flag)
+{
+ Mesh *me = BKE_mesh_from_object(ob);
+ ob->mode &= ~mode_flag;
+
+ if (mode_flag == OB_MODE_VERTEX_PAINT) {
+ if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
+ BKE_mesh_flush_select_from_polys(me);
+ }
+ else if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
+ BKE_mesh_flush_select_from_verts(me);
+ }
+ }
+ else if (mode_flag == OB_MODE_WEIGHT_PAINT) {
+ if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
+ BKE_mesh_flush_select_from_verts(me);
+ }
+ else if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
+ BKE_mesh_flush_select_from_polys(me);
+ }
}
else {
- EvaluationContext eval_ctx;
+ BLI_assert(0);
+ }
- CTX_data_eval_ctx(C, &eval_ctx);
+ /* If the cache is not released by a cancel or a done, free it now. */
+ if (ob->sculpt && ob->sculpt->cache) {
+ sculpt_cache_free(ob->sculpt->cache);
+ ob->sculpt->cache = NULL;
+ }
- ob->mode |= mode_flag;
+ BKE_sculptsession_free(ob);
- if (wp == NULL)
- wp = scene->toolsettings->wpaint = new_vpaint();
+ paint_cursor_delete_textures();
- paint_cursor_start(C, weight_paint_poll);
+ if (mode_flag == OB_MODE_WEIGHT_PAINT) {
+ ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
+ ED_mesh_mirror_topo_table(NULL, NULL, 'e');
+ }
+}
- BKE_paint_init(scene, ePaintWeight, PAINT_CURSOR_WEIGHT_PAINT);
+void ED_object_vpaintmode_exit_ex(Object *ob)
+{
+ ed_vwpaintmode_exit_generic(ob, OB_MODE_VERTEX_PAINT);
+}
+void ED_object_vpaintmode_exit(struct bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+ ED_object_vpaintmode_exit_ex(ob);
+}
- /* weight paint specific */
- ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 's');
- ED_vgroup_sync_from_pose(ob);
+void ED_object_wpaintmode_exit_ex(Object *ob)
+{
+ ed_vwpaintmode_exit_generic(ob, OB_MODE_WEIGHT_PAINT);
+}
+void ED_object_wpaintmode_exit(struct bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+ ED_object_wpaintmode_exit_ex(ob);
+}
- /* Create vertex/weight paint mode session data */
- if (ob->sculpt) {
- BKE_sculptsession_free(ob);
+/** \} */
+
+/* *************** set wpaint operator ****************** */
+
+/**
+ * \note Keep in sync with #vpaint_mode_toggle_exec
+ */
+static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ const int mode_flag = OB_MODE_WEIGHT_PAINT;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
+ Scene *scene = CTX_data_scene(C);
+
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
}
- vertex_paint_init_session(&eval_ctx, scene, ob);
}
- BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ Mesh *me = BKE_mesh_from_object(ob);
+
+ if (is_mode_set) {
+ ED_object_wpaintmode_exit_ex(ob);
+ }
+ else {
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ED_object_wpaintmode_enter_ex(&eval_ctx, wm, scene, ob);
+ }
/* Weightpaint works by overriding colors in mesh,
* so need to make sure we recalc on enter and
@@ -1285,14 +1405,11 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
bool *defbase_sel;
SculptSession *ss = ob->sculpt;
VPaint *vp = CTX_data_tool_settings(C)->wpaint;
- EvaluationContext eval_ctx;
if (ED_wpaint_ensure_data(C, op->reports, WPAINT_ENSURE_MIRROR, &vgroup_index) == false) {
return false;
}
- CTX_data_eval_ctx(C, &eval_ctx);
-
{
/* check if we are attempting to paint onto a locked vertex group,
* and other options disallow it from doing anything useful */
@@ -1339,7 +1456,7 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
/* make mode data storage */
wpd = MEM_callocN(sizeof(struct WPaintData), "WPaintData");
paint_stroke_set_mode_data(stroke, wpd);
- view3d_set_viewcontext(C, &wpd->vc);
+ ED_view3d_viewcontext_init(C, &wpd->vc);
view_angle_limits_init(&wpd->normal_angle_precalc, vp->paint.brush->falloff_angle,
(vp->paint.brush->flag & BRUSH_FRONTFACE_FALLOFF) != 0);
@@ -1390,6 +1507,9 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
wpd->precomputed_weight = MEM_mallocN(sizeof(float) * me->totvert, __func__);
}
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* If not previously created, create vertex/weight paint mode session data */
vertex_paint_init_session(&eval_ctx, scene, ob);
vwpaint_update_cache_invariants(C, vp, ss, op, mouse);
@@ -1832,7 +1952,8 @@ static void wpaint_paint_leaves(
/* threaded loop over nodes */
SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes, .vp = vp, .wpd = wpd, .wpi = wpi, .me = me, .C = C,
+ .C = C, .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
+ .vp = vp, .wpd = wpd, .wpi = wpi, .me = me,
};
/* Use this so average can modify its weight without touching the brush. */
@@ -2212,8 +2333,6 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
const int mode_flag = OB_MODE_VERTEX_PAINT;
const bool is_mode_set = (ob->mode & mode_flag) != 0;
Scene *scene = CTX_data_scene(C);
- VPaint *vp = scene->toolsettings->vpaint;
- Mesh *me;
if (!is_mode_set) {
if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
@@ -2221,54 +2340,17 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
}
}
- me = BKE_mesh_from_object(ob);
+ Mesh *me = BKE_mesh_from_object(ob);
/* toggle: end vpaint */
if (is_mode_set) {
- ob->mode &= ~mode_flag;
-
- if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
- BKE_mesh_flush_select_from_polys(me);
- }
- else if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
- BKE_mesh_flush_select_from_verts(me);
- }
-
- /* If the cache is not released by a cancel or a done, free it now. */
- if (ob->sculpt->cache) {
- sculpt_cache_free(ob->sculpt->cache);
- ob->sculpt->cache = NULL;
- }
-
- BKE_sculptsession_free(ob);
-
- paint_cursor_delete_textures();
+ ED_object_vpaintmode_exit_ex(ob);
}
else {
EvaluationContext eval_ctx;
-
CTX_data_eval_ctx(C, &eval_ctx);
-
- ob->mode |= mode_flag;
-
- ED_mesh_color_ensure(me, NULL);
-
- if (vp == NULL)
- vp = scene->toolsettings->vpaint = new_vpaint();
-
- paint_cursor_start(C, vertex_paint_poll);
-
- BKE_paint_init(scene, ePaintVertex, PAINT_CURSOR_VERTEX_PAINT);
-
- /* Create vertex/weight paint mode session data */
- if (ob->sculpt) {
- if (ob->sculpt->cache) {
- sculpt_cache_free(ob->sculpt->cache);
- ob->sculpt->cache = NULL;
- }
- BKE_sculptsession_free(ob);
- }
- vertex_paint_init_session(&eval_ctx, scene, ob);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ED_object_vpaintmode_enter_ex(&eval_ctx, wm, scene, ob);
}
BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
@@ -2376,7 +2458,7 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
/* make mode data storage */
vpd = MEM_callocN(sizeof(*vpd), "VPaintData");
paint_stroke_set_mode_data(stroke, vpd);
- view3d_set_viewcontext(C, &vpd->vc);
+ ED_view3d_viewcontext_init(C, &vpd->vc);
view_angle_limits_init(&vpd->normal_angle_precalc, vp->paint.brush->falloff_angle,
(vp->paint.brush->flag & BRUSH_FRONTFACE_FALLOFF) != 0);
@@ -2871,8 +2953,8 @@ static void vpaint_paint_leaves(
const Brush *brush = ob->sculpt->cache->brush;
SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes, .vp = vp, .vpd = vpd,
- .lcol = (uint *)me->mloopcol, .me = me, .C = C,
+ .C = C, .sd = sd, .ob = ob, .brush = brush, .nodes = nodes, .vp = vp, .vpd = vpd,
+ .lcol = (uint *)me->mloopcol, .me = me,
};
ParallelRangeSettings settings;
BLI_parallel_range_settings_defaults(&settings);
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_proj.c b/source/blender/editors/sculpt_paint/paint_vertex_proj.c
index 999c9dc7880..336f851d4c1 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_proj.c
@@ -78,8 +78,9 @@ struct VertProjUpdate {
/* -------------------------------------------------------------------- */
/* Internal Init */
-static void vpaint_proj_dm_map_cosnos_init__map_cb(void *userData, int index, const float co[3],
- const float no_f[3], const short no_s[3])
+static void vpaint_proj_dm_map_cosnos_init__map_cb(
+ void *userData, int index, const float co[3],
+ const float no_f[3], const short no_s[3])
{
struct VertProjHandle *vp_handle = userData;
DMCoNo *co_no = &vp_handle->vcosnos[index];
@@ -131,8 +132,9 @@ static void vpaint_proj_dm_map_cosnos_init(
/* Same as init but take mouse location into account */
-static void vpaint_proj_dm_map_cosnos_update__map_cb(void *userData, int index, const float co[3],
- const float no_f[3], const short no_s[3])
+static void vpaint_proj_dm_map_cosnos_update__map_cb(
+ void *userData, int index, const float co[3],
+ const float no_f[3], const short no_s[3])
{
struct VertProjUpdate *vp_update = userData;
struct VertProjHandle *vp_handle = vp_update->vp_handle;
@@ -144,9 +146,10 @@ static void vpaint_proj_dm_map_cosnos_update__map_cb(void *userData, int index,
/* first find distance to this vertex */
float co_ss[2]; /* screenspace */
- if (ED_view3d_project_float_object(vp_update->ar,
- co, co_ss,
- V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
+ if (ED_view3d_project_float_object(
+ vp_update->ar,
+ co, co_ss,
+ V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
{
const float dist_sq = len_squared_v2v2(vp_update->mval_fl, co_ss);
if (dist_sq > vp_handle->dists_sq[index]) {
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
index 1348847167c..3892b776440 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
@@ -182,7 +182,7 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even
Mesh *me;
bool changed = false;
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
me = BKE_mesh_from_object(vc.obact);
if (me && me->dvert && vc.v3d && vc.rv3d && (vc.obact->actdef != 0)) {
@@ -297,7 +297,7 @@ static const EnumPropertyItem *weight_paint_sample_enum_itemf(
ViewContext vc;
Mesh *me;
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
me = BKE_mesh_from_object(vc.obact);
if (me && me->dvert && vc.v3d && vc.rv3d && vc.obact->defbase.first) {
@@ -366,7 +366,7 @@ static int weight_sample_group_exec(bContext *C, wmOperator *op)
{
int type = RNA_enum_get(op->ptr, "group");
ViewContext vc;
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
BLI_assert(type + 1 >= 0);
vc.obact->actdef = type + 1;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c
index 4d70d82d5c6..51cd759b260 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c
@@ -43,6 +43,7 @@
#include "BKE_modifier.h"
#include "BKE_object_deform.h"
#include "BKE_report.h"
+#include "BKE_object.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -58,7 +59,6 @@ bool ED_wpaint_ensure_data(
bContext *C, struct ReportList *reports,
enum eWPaintFlag flag, struct WPaintVGroupIndex *vgroup_index)
{
- Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
Mesh *me = BKE_mesh_from_object(ob);
@@ -67,7 +67,7 @@ bool ED_wpaint_ensure_data(
vgroup_index->mirror = -1;
}
- if (scene->obedit) {
+ if (BKE_object_is_in_editmode(ob)) {
return false;
}
@@ -308,4 +308,4 @@ float ED_wpaint_blend_tool(
}
}
-/** \} */ \ No newline at end of file
+/** \} */
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index c9d550aa4bd..4a9d2597415 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -37,7 +37,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLI_dial.h"
+#include "BLI_dial_2d.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@@ -60,6 +60,7 @@
#include "BKE_image.h"
#include "BKE_key.h"
#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_modifier.h"
@@ -1562,7 +1563,7 @@ static float neighbor_average_mask(SculptSession *ss, unsigned vert)
static void bmesh_neighbor_average(float avg[3], BMVert *v)
{
/* logic for 3 or more is identical */
- const int vfcount = BM_vert_face_count_ex(v, 3);
+ const int vfcount = BM_vert_face_count_at_most(v, 3);
/* Don't modify corner vertices */
if (vfcount > 1) {
@@ -1577,7 +1578,7 @@ static void bmesh_neighbor_average(float avg[3], BMVert *v)
for (i = 0; i < ARRAY_SIZE(adj_v); i++) {
const BMVert *v_other = adj_v[i];
- if (vfcount != 2 || BM_vert_face_count_ex(v_other, 2) <= 2) {
+ if (vfcount != 2 || BM_vert_face_count_at_most(v_other, 2) <= 2) {
add_v3_v3(avg, v_other->co);
total++;
}
@@ -4595,19 +4596,17 @@ static bool sculpt_any_smooth_mode(const Brush *brush,
(brush->mask_tool == BRUSH_MASK_SMOOTH)));
}
-static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob)
+static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *brush)
{
SculptSession *ss = ob->sculpt;
if (ss->kb || ss->modifiers_active) {
EvaluationContext eval_ctx;
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
-
CTX_data_eval_ctx(C, &eval_ctx);
-
- BKE_sculpt_update_mesh_elements(&eval_ctx, CTX_data_scene(C), sd, ob,
- sculpt_any_smooth_mode(brush, ss->cache, 0), false);
+ Scene *scene = CTX_data_scene(C);
+ Sculpt *sd = scene->toolsettings->sculpt;
+ bool need_pmap = sculpt_any_smooth_mode(brush, ss->cache, 0);
+ BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, need_pmap, false);
}
}
@@ -4728,7 +4727,7 @@ bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
bool original;
ViewContext vc;
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
ob = vc.obact;
@@ -4736,7 +4735,9 @@ bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
cache = ss->cache;
original = (cache) ? cache->original : 0;
- sculpt_stroke_modifiers_check(C, ob);
+ const Brush *brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
+
+ sculpt_stroke_modifiers_check(C, ob, brush);
depth = sculpt_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, original);
@@ -4762,7 +4763,6 @@ bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
}
if (hit == false) {
- const Brush *brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
if (ELEM(brush->falloff_shape, PAINT_FALLOFF_SHAPE_TUBE)) {
SculptFindNearestToRayData srd = {
.original = original,
@@ -4953,7 +4953,7 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *UNUSED(st
SculptSession *ss = ob->sculpt;
const Brush *brush = BKE_paint_brush(&sd->paint);
- sculpt_stroke_modifiers_check(C, ob);
+ sculpt_stroke_modifiers_check(C, ob, brush);
sculpt_update_cache_variants(C, sd, ob, itemptr);
sculpt_restore_mesh(sd, ob);
@@ -5028,7 +5028,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
BLI_assert(brush == ss->cache->brush); /* const, so we shouldn't change. */
ups->draw_inverted = false;
- sculpt_stroke_modifiers_check(C, ob);
+ sculpt_stroke_modifiers_check(C, ob, brush);
/* Alt-Smooth */
if (ss->cache->alt_smooth) {
@@ -5047,7 +5047,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
sculpt_cache_free(ss->cache);
ss->cache = NULL;
- sculpt_undo_push_end(C);
+ sculpt_undo_push_end();
BKE_pbvh_update(ss->pbvh, PBVH_UpdateOriginalBB, NULL);
@@ -5255,24 +5255,21 @@ void sculpt_dyntopo_node_layers_add(SculptSession *ss)
}
-void sculpt_update_after_dynamic_topology_toggle(bContext *C)
+void sculpt_update_after_dynamic_topology_toggle(
+ const EvaluationContext *eval_ctx,
+ Scene *scene, Object *ob)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- EvaluationContext eval_ctx;
Sculpt *sd = scene->toolsettings->sculpt;
- CTX_data_eval_ctx(C, &eval_ctx);
-
/* Create the PBVH */
- BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, false, false);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ BKE_sculpt_update_mesh_elements(eval_ctx, scene, sd, ob, false, false);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
}
-void sculpt_dynamic_topology_enable(bContext *C)
+void sculpt_dynamic_topology_enable_ex(
+ const EvaluationContext *eval_ctx,
+ Scene *scene, Object *ob)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
Mesh *me = ob->data;
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me);
@@ -5308,17 +5305,17 @@ void sculpt_dynamic_topology_enable(bContext *C)
ss->bm_log = BM_log_create(ss->bm);
/* Refresh */
- sculpt_update_after_dynamic_topology_toggle(C);
+ sculpt_update_after_dynamic_topology_toggle(eval_ctx, scene, ob);
}
/* Free the sculpt BMesh and BMLog
*
* If 'unode' is given, the BMesh's data is copied out to the unode
* before the BMesh is deleted so that it can be restored from */
-void sculpt_dynamic_topology_disable(bContext *C,
- SculptUndoNode *unode)
+void sculpt_dynamic_topology_disable_ex(
+ const EvaluationContext *eval_ctx,
+ Scene *scene, Object *ob, SculptUndoNode *unode)
{
- Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
Mesh *me = ob->data;
@@ -5367,28 +5364,59 @@ void sculpt_dynamic_topology_disable(bContext *C,
}
/* Refresh */
- sculpt_update_after_dynamic_topology_toggle(C);
+ sculpt_update_after_dynamic_topology_toggle(eval_ctx, scene, ob);
}
+void sculpt_dynamic_topology_disable(bContext *C, SculptUndoNode *unode)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+ sculpt_dynamic_topology_disable_ex(&eval_ctx, scene, ob, unode);
+}
+
+static void sculpt_dynamic_topology_disable_with_undo(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
+{
+ SculptSession *ss = ob->sculpt;
+ if (ss->bm) {
+ sculpt_undo_push_begin("Dynamic topology disable");
+ sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END);
+ sculpt_dynamic_topology_disable_ex(eval_ctx, scene, ob, NULL);
+ sculpt_undo_push_end();
+ }
+}
+
+static void sculpt_dynamic_topology_enable_with_undo(
+ const EvaluationContext *eval_ctx,
+ Scene *scene, Object *ob)
+{
+ SculptSession *ss = ob->sculpt;
+ if (ss->bm == NULL) {
+ sculpt_undo_push_begin("Dynamic topology enable");
+ sculpt_dynamic_topology_enable_ex(eval_ctx, scene, ob);
+ sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
+ sculpt_undo_push_end();
+ }
+}
static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
WM_cursor_wait(1);
if (ss->bm) {
- sculpt_undo_push_begin("Dynamic topology disable");
- sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END);
- sculpt_dynamic_topology_disable(C, NULL);
+ sculpt_dynamic_topology_disable_with_undo(&eval_ctx, scene, ob);
}
else {
- sculpt_undo_push_begin("Dynamic topology enable");
- sculpt_dynamic_topology_enable(C);
- sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
+ sculpt_dynamic_topology_enable_with_undo(&eval_ctx, scene, ob);
}
- sculpt_undo_push_end(C);
WM_cursor_wait(0);
@@ -5431,13 +5459,11 @@ static int dyntopo_warning_popup(bContext *C, wmOperatorType *ot, enum eDynTopoW
return OPERATOR_INTERFACE;
}
-static enum eDynTopoWarnFlag sculpt_dynamic_topology_check(bContext *C)
+static enum eDynTopoWarnFlag sculpt_dynamic_topology_check(Scene *scene, Object *ob)
{
- Object *ob = CTX_data_active_object(C);
Mesh *me = ob->data;
SculptSession *ss = ob->sculpt;
- Scene *scene = CTX_data_scene(C);
enum eDynTopoWarnFlag flag = 0;
BLI_assert(ss->bm == NULL);
@@ -5482,7 +5508,8 @@ static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, co
SculptSession *ss = ob->sculpt;
if (!ss->bm) {
- enum eDynTopoWarnFlag flag = sculpt_dynamic_topology_check(C);
+ Scene *scene = CTX_data_scene(C);
+ enum eDynTopoWarnFlag flag = sculpt_dynamic_topology_check(scene, ob);
if (flag) {
/* The mesh has customdata that will be lost, let the user confirm this is OK */
@@ -5576,7 +5603,7 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op))
/* Finish undo */
BM_log_all_added(ss->bm, ss->bm_log);
- sculpt_undo_push_end(C);
+ sculpt_undo_push_end();
/* Redraw */
sculpt_pbvh_clear(ob);
@@ -5599,177 +5626,215 @@ static void SCULPT_OT_symmetrize(wmOperatorType *ot)
/**** Toggle operator for turning sculpt mode on or off ****/
-static void sculpt_init_session(const bContext *C, Scene *scene, Object *ob)
+static void sculpt_init_session(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
- EvaluationContext eval_ctx;
-
- CTX_data_eval_ctx(C, &eval_ctx);
+ /* Create persistent sculpt mode data */
+ BKE_sculpt_toolsettings_data_ensure(scene);
ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
-
- BKE_sculpt_update_mesh_elements(&eval_ctx, scene, scene->toolsettings->sculpt, ob, 0, false);
+ ob->sculpt->mode_type = OB_MODE_SCULPT;
+ BKE_sculpt_update_mesh_elements(eval_ctx, scene, scene->toolsettings->sculpt, ob, 0, false);
}
+static int ed_object_sculptmode_flush_recalc_flag(Scene *scene, Object *ob, MultiresModifierData *mmd)
+{
+ int flush_recalc = 0;
+ /* multires in sculpt mode could have different from object mode subdivision level */
+ flush_recalc |= mmd && mmd->sculptlvl != mmd->lvl;
+ /* if object has got active modifiers, it's dm could be different in sculpt mode */
+ flush_recalc |= sculpt_has_active_modifiers(scene, ob);
+ return flush_recalc;
+}
-static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
+void ED_object_sculptmode_enter_ex(
+ const EvaluationContext *eval_ctx,
+ Scene *scene, Object *ob,
+ ReportList *reports)
{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- Object *ob = CTX_data_active_object(C);
const int mode_flag = OB_MODE_SCULPT;
- const bool is_mode_set = (ob->mode & mode_flag) != 0;
- Mesh *me;
+ Mesh *me = BKE_mesh_from_object(ob);
+
+ /* Enter sculptmode */
+ ob->mode |= mode_flag;
+
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
- int flush_recalc = 0;
- if (!is_mode_set) {
- if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
- return OPERATOR_CANCELLED;
- }
+ const int flush_recalc = ed_object_sculptmode_flush_recalc_flag(scene, ob, mmd);
+
+ if (flush_recalc)
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+
+ /* Create sculpt mode session data */
+ if (ob->sculpt) {
+ BKE_sculptsession_free(ob);
}
- me = BKE_mesh_from_object(ob);
+ sculpt_init_session(eval_ctx, scene, ob);
- /* multires in sculpt mode could have different from object mode subdivision level */
- flush_recalc |= mmd && mmd->sculptlvl != mmd->lvl;
- /* if object has got active modifiers, it's dm could be different in sculpt mode */
- flush_recalc |= sculpt_has_active_modifiers(scene, ob);
+ /* Mask layer is required */
+ if (mmd) {
+ /* XXX, we could attempt to support adding mask data mid-sculpt mode (with multi-res)
+ * but this ends up being quite tricky (and slow) */
+ BKE_sculpt_mask_layers_ensure(ob, mmd);
+ }
- if (is_mode_set) {
- if (mmd)
- multires_force_update(ob);
+ if (!(fabsf(ob->size[0] - ob->size[1]) < 1e-4f && fabsf(ob->size[1] - ob->size[2]) < 1e-4f)) {
+ BKE_report(reports, RPT_WARNING,
+ "Object has non-uniform scale, sculpting may be unpredictable");
+ }
+ else if (is_negative_m4(ob->obmat)) {
+ BKE_report(reports, RPT_WARNING,
+ "Object has negative scale, sculpting may be unpredictable");
+ }
- /* Always for now, so leaving sculpt mode always ensures scene is in
- * a consistent state.
- */
- if (true || flush_recalc || (ob->sculpt && ob->sculpt->bm)) {
- DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
+ Paint *paint = BKE_paint_get_active_from_paintmode(scene, ePaintSculpt);
+ BKE_paint_init(scene, ePaintSculpt, PAINT_CURSOR_SCULPT);
- if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
- /* Dynamic topology must be disabled before exiting sculpt
- * mode to ensure the undo stack stays in a consistent
- * state */
- sculpt_dynamic_topology_toggle_exec(C, NULL);
+ paint_cursor_start_explicit(paint, G.main->wm.first, sculpt_poll_view3d);
- /* store so we know to re-enable when entering sculpt mode */
- me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
+ /* Check dynamic-topology flag; re-enter dynamic-topology mode when changing modes,
+ * As long as no data was added that is not supported. */
+ if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
+ const char *message_unsupported = NULL;
+ if (me->totloop != me->totpoly * 3) {
+ message_unsupported = TIP_("non-triangle face");
+ }
+ else if (mmd != NULL) {
+ message_unsupported = TIP_("multi-res modifier");
+ }
+ else {
+ enum eDynTopoWarnFlag flag = sculpt_dynamic_topology_check(scene, ob);
+ if (flag == 0) {
+ /* pass */
+ }
+ else if (flag & DYNTOPO_WARN_VDATA) {
+ message_unsupported = TIP_("vertex data");
+ }
+ else if (flag & DYNTOPO_WARN_EDATA) {
+ message_unsupported = TIP_("edge data");
+ }
+ else if (flag & DYNTOPO_WARN_LDATA) {
+ message_unsupported = TIP_("face data");
+ }
+ else if (flag & DYNTOPO_WARN_MODIFIER) {
+ message_unsupported = TIP_("constructive modifier");
+ }
+ else {
+ BLI_assert(0);
+ }
}
- /* Leave sculptmode */
- ob->mode &= ~mode_flag;
+ if (message_unsupported == NULL) {
+ /* undo push is needed to prevent memory leak */
+ sculpt_undo_push_begin("Dynamic topology enable");
+ sculpt_dynamic_topology_enable_ex(eval_ctx, scene, ob);
+ sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
+ }
+ else {
+ BKE_reportf(reports, RPT_WARNING,
+ "Dynamic Topology found: %s, disabled",
+ message_unsupported);
+ me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
+ }
+ }
- BKE_sculptsession_free(ob);
+ // ED_workspace_object_mode_sync_from_object(G.main->wm.first, workspace, ob);
- paint_cursor_delete_textures();
+ /* VBO no longer valid */
+ if (ob->derivedFinal) {
+ GPU_drawobject_free(ob->derivedFinal);
}
- else {
- /* Enter sculptmode */
- ob->mode |= mode_flag;
+}
- if (flush_recalc)
- DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+void ED_object_sculptmode_enter(struct bContext *C, ReportList *reports)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+ ED_object_sculptmode_enter_ex(&eval_ctx, scene, ob, reports);
+}
- /* Create persistent sculpt mode data */
- if (!ts->sculpt) {
- ts->sculpt = MEM_callocN(sizeof(Sculpt), "sculpt mode data");
+void ED_object_sculptmode_exit_ex(
+ const EvaluationContext *eval_ctx,
+ Scene *scene, Object *ob)
+{
+ const int mode_flag = OB_MODE_SCULPT;
+ Mesh *me = BKE_mesh_from_object(ob);
- /* Turn on X plane mirror symmetry by default */
- ts->sculpt->paint.symmetry_flags |= PAINT_SYMM_X;
- ts->sculpt->paint.flags |= PAINT_SHOW_BRUSH;
+ MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
+ if (mmd) {
+ multires_force_update(ob);
+ }
- /* Make sure at least dyntopo subdivision is enabled */
- ts->sculpt->flags |= SCULPT_DYNTOPO_SUBDIVIDE | SCULPT_DYNTOPO_COLLAPSE;
- }
+ /* Not needed for now. */
+#if 0
+ const int flush_recalc = ed_object_sculptmode_flush_recalc_flag(scene, ob, mmd);
+#endif
- if (!ts->sculpt->detail_size)
- ts->sculpt->detail_size = 12;
- if (!ts->sculpt->detail_percent)
- ts->sculpt->detail_percent = 25;
- if (ts->sculpt->constant_detail == 0.0f)
- ts->sculpt->constant_detail = 3.0f;
+ /* Always for now, so leaving sculpt mode always ensures scene is in
+ * a consistent state.
+ */
+ if (true || /* flush_recalc || */ (ob->sculpt && ob->sculpt->bm)) {
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
- /* Set sane default tiling offsets */
- if (!ts->sculpt->paint.tile_offset[0]) ts->sculpt->paint.tile_offset[0] = 1.0f;
- if (!ts->sculpt->paint.tile_offset[1]) ts->sculpt->paint.tile_offset[1] = 1.0f;
- if (!ts->sculpt->paint.tile_offset[2]) ts->sculpt->paint.tile_offset[2] = 1.0f;
+ if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
+ /* Dynamic topology must be disabled before exiting sculpt
+ * mode to ensure the undo stack stays in a consistent
+ * state */
+ sculpt_dynamic_topology_disable_with_undo(eval_ctx, scene, ob);
+ /* store so we know to re-enable when entering sculpt mode */
+ me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
+ }
- /* Create sculpt mode session data */
- if (ob->sculpt)
- BKE_sculptsession_free(ob);
+ /* Leave sculptmode */
+ ob->mode &= ~mode_flag;
- sculpt_init_session(C, scene, ob);
+ // ED_workspace_object_mode_sync_from_object(G.main->wm.first, workspace, ob);
- /* Mask layer is required */
- if (mmd) {
- /* XXX, we could attempt to support adding mask data mid-sculpt mode (with multi-res)
- * but this ends up being quite tricky (and slow) */
- BKE_sculpt_mask_layers_ensure(ob, mmd);
- }
+ BKE_sculptsession_free(ob);
- if (!(fabsf(ob->size[0] - ob->size[1]) < 1e-4f && fabsf(ob->size[1] - ob->size[2]) < 1e-4f)) {
- BKE_report(op->reports, RPT_WARNING,
- "Object has non-uniform scale, sculpting may be unpredictable");
- }
- else if (is_negative_m4(ob->obmat)) {
- BKE_report(op->reports, RPT_WARNING,
- "Object has negative scale, sculpting may be unpredictable");
- }
+ paint_cursor_delete_textures();
- BKE_paint_init(scene, ePaintSculpt, PAINT_CURSOR_SCULPT);
+ /* VBO no longer valid */
+ if (ob->derivedFinal) {
+ GPU_drawobject_free(ob->derivedFinal);
+ }
+}
- paint_cursor_start(C, sculpt_poll_view3d);
+void ED_object_sculptmode_exit(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+ ED_object_sculptmode_exit_ex(&eval_ctx, scene, ob);
+}
- /* Check dynamic-topology flag; re-enter dynamic-topology mode when changing modes,
- * As long as no data was added that is not supported. */
- if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
- const char *message_unsupported = NULL;
- if (me->totloop != me->totpoly * 3) {
- message_unsupported = TIP_("non-triangle face");
- }
- else if (mmd != NULL) {
- message_unsupported = TIP_("multi-res modifier");
- }
- else {
- enum eDynTopoWarnFlag flag = sculpt_dynamic_topology_check(C);
- if (flag == 0) {
- /* pass */
- }
- else if (flag & DYNTOPO_WARN_VDATA) {
- message_unsupported = TIP_("vertex data");
- }
- else if (flag & DYNTOPO_WARN_EDATA) {
- message_unsupported = TIP_("edge data");
- }
- else if (flag & DYNTOPO_WARN_LDATA) {
- message_unsupported = TIP_("face data");
- }
- else if (flag & DYNTOPO_WARN_MODIFIER) {
- message_unsupported = TIP_("constructive modifier");
- }
- else {
- BLI_assert(0);
- }
- }
+static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ const int mode_flag = OB_MODE_SCULPT;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
- if (message_unsupported == NULL) {
- /* undo push is needed to prevent memory leak */
- sculpt_undo_push_begin("Dynamic topology enable");
- sculpt_dynamic_topology_enable(C);
- sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
- }
- else {
- BKE_reportf(op->reports, RPT_WARNING,
- "Dynamic Topology found: %s, disabled",
- message_unsupported);
- me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
- }
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
}
}
- if (ob->derivedFinal) /* VBO no longer valid */
- GPU_drawobject_free(ob->derivedFinal);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ if (is_mode_set) {
+ ED_object_sculptmode_exit_ex(&eval_ctx, scene, ob);
+ }
+ else {
+ ED_object_sculptmode_enter_ex(&eval_ctx, scene, ob, op->reports);
+ }
WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
@@ -5839,7 +5904,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
}
MEM_freeN(nodes);
- sculpt_undo_push_end(C);
+ sculpt_undo_push_end();
/* force rebuild of pbvh for better BB placement */
sculpt_pbvh_clear(ob);
@@ -5871,12 +5936,14 @@ static void sample_detail(bContext *C, int ss_co[2])
float ray_start[3], ray_end[3], ray_normal[3], depth;
SculptDetailRaycastData srd;
float mouse[2] = {ss_co[0], ss_co[1]};
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
sd = CTX_data_tool_settings(C)->sculpt;
ob = vc.obact;
- sculpt_stroke_modifiers_check(C, ob);
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ sculpt_stroke_modifiers_check(C, ob, brush);
depth = sculpt_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, false);
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 5fb9eee805f..ba39d51700d 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -60,10 +60,19 @@ bool sculpt_stroke_get_location(struct bContext *C, float out[3], const float mo
/* Dynamic topology */
void sculpt_pbvh_clear(Object *ob);
void sculpt_dyntopo_node_layers_add(struct SculptSession *ss);
-void sculpt_update_after_dynamic_topology_toggle(struct bContext *C);
-void sculpt_dynamic_topology_enable(struct bContext *C);
-void sculpt_dynamic_topology_disable(struct bContext *C,
- struct SculptUndoNode *unode);
+void sculpt_update_after_dynamic_topology_toggle(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene, struct Object *ob);
+void sculpt_dynamic_topology_enable_ex(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene, struct Object *ob);
+void sculpt_dynamic_topology_enable(bContext *C);
+
+void sculpt_dynamic_topology_disable_ex(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene, struct Object *ob,
+ struct SculptUndoNode *unode);
+void sculpt_dynamic_topology_disable(bContext *C, struct SculptUndoNode *unode);
/* Undo */
@@ -116,6 +125,8 @@ typedef struct SculptUndoNode {
/* shape keys */
char shapeName[sizeof(((KeyBlock *)0))->name];
+
+ size_t undo_size;
} SculptUndoNode;
/* Factor of brush to have rake point following behind
@@ -342,7 +353,7 @@ void sculpt_cache_free(StrokeCache *cache);
SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type);
SculptUndoNode *sculpt_undo_get_node(PBVHNode *node);
void sculpt_undo_push_begin(const char *name);
-void sculpt_undo_push_end(const struct bContext *C);
+void sculpt_undo_push_end(void);
void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]);
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 63017a0e576..e12ef2df4ab 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -48,6 +48,9 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_workspace_types.h"
#include "BKE_ccg.h"
#include "BKE_context.h"
@@ -56,6 +59,8 @@
#include "BKE_key.h"
#include "BKE_mesh.h"
#include "BKE_subsurf.h"
+#include "BKE_undo_system.h"
+
#include "DEG_depsgraph.h"
#include "WM_api.h"
@@ -64,12 +69,22 @@
#include "GPU_buffers.h"
#include "ED_paint.h"
+#include "ED_object.h"
+#include "ED_sculpt.h"
+#include "ED_undo.h"
#include "bmesh.h"
#include "paint_intern.h"
#include "sculpt_intern.h"
-/************************** Undo *************************/
+
+typedef struct UndoSculpt {
+ ListBase nodes;
+
+ size_t undo_size;
+} UndoSculpt;
+
+static UndoSculpt *sculpt_undo_get_nodes(void);
static void update_cb(PBVHNode *node, void *rebuild)
{
@@ -368,8 +383,8 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C,
}
/* Create empty sculpt BMesh and enable logging */
-static void sculpt_undo_bmesh_enable(Object *ob,
- SculptUndoNode *unode)
+static void sculpt_undo_bmesh_enable(
+ Object *ob, SculptUndoNode *unode)
{
SculptSession *ss = ob->sculpt;
Mesh *me = ob->data;
@@ -457,7 +472,7 @@ static int sculpt_undo_bmesh_restore(bContext *C,
return false;
}
-static void sculpt_undo_restore(bContext *C, ListBase *lb)
+static void sculpt_undo_restore_list(bContext *C, ListBase *lb)
{
Scene *scene = CTX_data_scene(C);
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
@@ -580,7 +595,7 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
}
}
-static void sculpt_undo_free(ListBase *lb)
+static void sculpt_undo_free_list(ListBase *lb)
{
SculptUndoNode *unode;
int i;
@@ -623,6 +638,8 @@ static void sculpt_undo_free(ListBase *lb)
}
}
+/* Most likely we don't need this. */
+#if 0
static bool sculpt_undo_cleanup(bContext *C, ListBase *lb)
{
Object *ob = CTX_data_active_object(C);
@@ -639,16 +656,17 @@ static bool sculpt_undo_cleanup(bContext *C, ListBase *lb)
return false;
}
+#endif
SculptUndoNode *sculpt_undo_get_node(PBVHNode *node)
{
- ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_MESH);
+ UndoSculpt *usculpt = sculpt_undo_get_nodes();
- if (!lb) {
+ if (usculpt == NULL) {
return NULL;
}
- return BLI_findptr(lb, node, offsetof(SculptUndoNode, node));
+ return BLI_findptr(&usculpt->nodes, node, offsetof(SculptUndoNode, node));
}
static void sculpt_undo_alloc_and_store_hidden(PBVH *pbvh,
@@ -674,10 +692,11 @@ static void sculpt_undo_alloc_and_store_hidden(PBVH *pbvh,
}
}
-static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
- SculptUndoType type)
+static SculptUndoNode *sculpt_undo_alloc_node(
+ Object *ob, PBVHNode *node,
+ SculptUndoType type)
{
- ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_MESH);
+ UndoSculpt *usculpt = sculpt_undo_get_nodes();
SculptUndoNode *unode;
SculptSession *ss = ob->sculpt;
int totvert, allvert, totgrid, maxgrid, gridsize, *grids;
@@ -702,23 +721,23 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
/* general TODO, fix count_alloc */
switch (type) {
case SCULPT_UNDO_COORDS:
- unode->co = MEM_mapallocN(sizeof(float) * 3 * allvert, "SculptUndoNode.co");
- unode->no = MEM_mapallocN(sizeof(short) * 3 * allvert, "SculptUndoNode.no");
- undo_paint_push_count_alloc(UNDO_PAINT_MESH,
- (sizeof(float) * 3 +
- sizeof(short) * 3 +
- sizeof(int)) * allvert);
+ unode->co = MEM_mapallocN(sizeof(float[3]) * allvert, "SculptUndoNode.co");
+ unode->no = MEM_mapallocN(sizeof(short[3]) * allvert, "SculptUndoNode.no");
+
+ usculpt->undo_size = (sizeof(float[3]) + sizeof(short[3]) + sizeof(int)) * allvert;
break;
case SCULPT_UNDO_HIDDEN:
if (maxgrid)
sculpt_undo_alloc_and_store_hidden(ss->pbvh, unode);
else
unode->vert_hidden = BLI_BITMAP_NEW(allvert, "SculptUndoNode.vert_hidden");
-
+
break;
case SCULPT_UNDO_MASK:
unode->mask = MEM_mapallocN(sizeof(float) * allvert, "SculptUndoNode.mask");
- undo_paint_push_count_alloc(UNDO_PAINT_MESH, (sizeof(float) * sizeof(int)) * allvert);
+
+ usculpt->undo_size += (sizeof(float) * sizeof(int)) * allvert;
+
break;
case SCULPT_UNDO_DYNTOPO_BEGIN:
case SCULPT_UNDO_DYNTOPO_END:
@@ -727,7 +746,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
break;
}
- BLI_addtail(lb, unode);
+ BLI_addtail(&usculpt->nodes, unode);
if (maxgrid) {
/* multires */
@@ -804,12 +823,13 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
PBVHNode *node,
SculptUndoType type)
{
- ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_MESH);
- SculptUndoNode *unode = lb->first;
+ UndoSculpt *usculpt = sculpt_undo_get_nodes();
SculptSession *ss = ob->sculpt;
PBVHVertexIter vd;
- if (!lb->first) {
+ SculptUndoNode *unode = usculpt->nodes.first;
+
+ if (unode == NULL) {
unode = MEM_callocN(sizeof(*unode), __func__);
BLI_strncpy(unode->idname, ob->id.name, sizeof(unode->idname));
@@ -848,7 +868,7 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
unode->bm_entry = BM_log_entry_add(ss->bm_log);
}
- BLI_addtail(lb, unode);
+ BLI_addtail(&usculpt->nodes, unode);
}
if (node) {
@@ -889,14 +909,15 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
return unode;
}
-SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
- SculptUndoType type)
+SculptUndoNode *sculpt_undo_push_node(
+ Object *ob, PBVHNode *node,
+ SculptUndoType type)
{
SculptSession *ss = ob->sculpt;
SculptUndoNode *unode;
/* list is manipulated by multiple threads, so we lock */
- BLI_lock_thread(LOCK_CUSTOM1);
+ BLI_thread_lock(LOCK_CUSTOM1);
if (ss->bm ||
ELEM(type,
@@ -906,17 +927,17 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
/* Dynamic topology stores only one undo node per stroke,
* regardless of the number of PBVH nodes modified */
unode = sculpt_undo_bmesh_push(ob, node, type);
- BLI_unlock_thread(LOCK_CUSTOM1);
+ BLI_thread_unlock(LOCK_CUSTOM1);
return unode;
}
else if ((unode = sculpt_undo_get_node(node))) {
- BLI_unlock_thread(LOCK_CUSTOM1);
+ BLI_thread_unlock(LOCK_CUSTOM1);
return unode;
}
unode = sculpt_undo_alloc_node(ob, node, type);
- BLI_unlock_thread(LOCK_CUSTOM1);
+ BLI_thread_unlock(LOCK_CUSTOM1);
/* copy threaded, hopefully this is the performance critical part */
@@ -960,17 +981,18 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
void sculpt_undo_push_begin(const char *name)
{
- ED_undo_paint_push_begin(UNDO_PAINT_MESH, name,
- sculpt_undo_restore, sculpt_undo_free, sculpt_undo_cleanup);
+ UndoStack *ustack = ED_undo_stack_get();
+ bContext *C = NULL; /* special case, we never read from this. */
+ BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_SCULPT);
}
-void sculpt_undo_push_end(const bContext *C)
+void sculpt_undo_push_end(void)
{
- ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_MESH);
+ UndoSculpt *usculpt = sculpt_undo_get_nodes();
SculptUndoNode *unode;
/* we don't need normals in the undo stack */
- for (unode = lb->first; unode; unode = unode->next) {
+ for (unode = usculpt->nodes.first; unode; unode = unode->next) {
if (unode->no) {
MEM_freeN(unode->no);
unode->no = NULL;
@@ -980,7 +1002,97 @@ void sculpt_undo_push_end(const bContext *C)
BKE_pbvh_node_layer_disp_free(unode->node);
}
- ED_undo_paint_push_end(UNDO_PAINT_MESH);
+ UndoStack *ustack = ED_undo_stack_get();
+ BKE_undosys_step_push(ustack, NULL, NULL);
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Implements ED Undo System
+ * \{ */
+
+typedef struct SculptUndoStep {
+ UndoStep step;
+ /* note: will split out into list for multi-object-sculpt-mode. */
+ UndoSculpt data;
+} SculptUndoStep;
+
+static bool sculpt_undosys_poll(bContext *C)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa && (sa->spacetype == SPACE_VIEW3D)) {
+ Object *obact = CTX_data_active_object(C);
+ if (obact && (obact->mode & OB_MODE_SCULPT)) {
+ return true;
+ }
+ }
+ return false;
+}
- WM_file_tag_modified(C);
+static void sculpt_undosys_step_encode_init(struct bContext *UNUSED(C), UndoStep *us_p)
+{
+ SculptUndoStep *us = (SculptUndoStep *)us_p;
+ /* dummy, memory is cleared anyway. */
+ BLI_listbase_clear(&us->data.nodes);
}
+
+static bool sculpt_undosys_step_encode(struct bContext *UNUSED(C), UndoStep *us_p)
+{
+ /* dummy, encoding is done along the way by adding tiles
+ * to the current 'SculptUndoStep' added by encode_init. */
+ SculptUndoStep *us = (SculptUndoStep *)us_p;
+ us->step.data_size = us->data.undo_size;
+ return true;
+}
+
+static void sculpt_undosys_step_decode(struct bContext *C, UndoStep *us_p, int UNUSED(dir))
+{
+ /* TODO(campbell): undo_system: use low-level API to set mode. */
+ ED_object_mode_set(C, OB_MODE_SCULPT);
+ BLI_assert(sculpt_undosys_poll(C));
+
+ SculptUndoStep *us = (SculptUndoStep *)us_p;
+ sculpt_undo_restore_list(C, &us->data.nodes);
+}
+
+static void sculpt_undosys_step_free(UndoStep *us_p)
+{
+ SculptUndoStep *us = (SculptUndoStep *)us_p;
+ sculpt_undo_free_list(&us->data.nodes);
+}
+
+/* Export for ED_undo_sys. */
+void ED_sculpt_undosys_type(UndoType *ut)
+{
+ ut->name = "Sculpt";
+ ut->poll = sculpt_undosys_poll;
+ ut->step_encode_init = sculpt_undosys_step_encode_init;
+ ut->step_encode = sculpt_undosys_step_encode;
+ ut->step_decode = sculpt_undosys_step_decode;
+ ut->step_free = sculpt_undosys_step_free;
+
+ ut->mode = BKE_UNDOTYPE_MODE_ACCUMULATE;
+ ut->use_context = true;
+
+ ut->step_size = sizeof(SculptUndoStep);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Utilities
+ * \{ */
+
+static UndoSculpt *sculpt_undosys_step_get_nodes(UndoStep *us_p)
+{
+ SculptUndoStep *us = (SculptUndoStep *)us_p;
+ return &us->data;
+}
+
+static UndoSculpt *sculpt_undo_get_nodes(void)
+{
+ UndoStack *ustack = ED_undo_stack_get();
+ UndoStep *us = BKE_undosys_stack_init_or_active_with_type(ustack, BKE_UNDOSYS_TYPE_SCULPT);
+ return sculpt_undosys_step_get_nodes(us);
+}
+
+/** \} */
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index c9453f94e61..6928610f280 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -650,9 +650,9 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
/* we need to find the active island here */
if (do_island_optimization) {
UvElement *element;
- NearestHit hit;
+ UvNearestHit hit = UV_NEAREST_HIT_INIT;
Image *ima = CTX_data_edit_image(C);
- uv_find_nearest_vert(scene, ima, em, co, NULL, &hit);
+ uv_find_nearest_vert(scene, ima, obedit, co, 0.0f, &hit);
element = BM_uv_element_get(data->elementMap, hit.efa, hit.l);
island_index = element->island;
@@ -759,7 +759,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
MEM_freeN(uniqueUv);
/* Allocate connectivity data, we allocate edges once */
- data->uvedges = MEM_mallocN(sizeof(*data->uvedges) * BLI_ghash_size(edgeHash), "uv_brush_edge_connectivity_data");
+ data->uvedges = MEM_mallocN(sizeof(*data->uvedges) * BLI_ghash_len(edgeHash), "uv_brush_edge_connectivity_data");
if (!data->uvedges) {
BLI_ghash_free(edgeHash, NULL, NULL);
MEM_freeN(edges);
@@ -772,7 +772,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
GHASH_ITER (gh_iter, edgeHash) {
data->uvedges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(&gh_iter));
}
- data->totalUvEdges = BLI_ghash_size(edgeHash);
+ data->totalUvEdges = BLI_ghash_len(edgeHash);
/* cleanup temporary stuff */
BLI_ghash_free(edgeHash, NULL, NULL);
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index daeb7823a43..a01b4aa1b18 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -311,7 +311,6 @@ static int sound_bake_animation_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
int oldfra = scene->r.cfra;
int cfra;
@@ -320,11 +319,11 @@ static int sound_bake_animation_exec(bContext *C, wmOperator *UNUSED(op))
for (cfra = (scene->r.sfra > 0) ? (scene->r.sfra - 1) : 0; cfra <= scene->r.efra + 1; cfra++) {
scene->r.cfra = cfra;
- BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
}
scene->r.cfra = oldfra;
- BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_action/action_buttons.c b/source/blender/editors/space_action/action_buttons.c
index 80ec9107984..3ba59b3be75 100644
--- a/source/blender/editors/space_action/action_buttons.c
+++ b/source/blender/editors/space_action/action_buttons.c
@@ -49,8 +49,6 @@
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_fcurve.h"
-#include "BKE_main.h"
-#include "BKE_global.h"
#include "BKE_screen.h"
#include "BKE_unit.h"
diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c
index 29b3c6f2f6c..f1153b5bed0 100644
--- a/source/blender/editors/space_action/action_data.c
+++ b/source/blender/editors/space_action/action_data.c
@@ -54,10 +54,8 @@
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_fcurve.h"
-#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_key.h"
-#include "BKE_main.h"
#include "BKE_nla.h"
#include "BKE_scene.h"
#include "BKE_context.h"
@@ -568,11 +566,11 @@ void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act,
if (strip->act == act) {
/* Remove this strip, and the track too if it doesn't have anything else */
- free_nlastrip(&nlt->strips, strip);
+ BKE_nlastrip_free(&nlt->strips, strip);
if (nlt->strips.first == NULL) {
BLI_assert(nstrip == NULL);
- free_nlatrack(&adt->nla_tracks, nlt);
+ BKE_nlatrack_free(&adt->nla_tracks, nlt);
}
}
}
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index 72b1245ca8a..1c15a7c5950 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -59,7 +59,6 @@
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_key.h"
-#include "BKE_main.h"
#include "BKE_nla.h"
#include "BKE_context.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 110c4d1789d..2b974ac73d7 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -36,7 +36,7 @@
#include "BLI_blenlib.h"
#include "BLI_dlrbTree.h"
-#include "BLI_lasso.h"
+#include "BLI_lasso_2d.h"
#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
@@ -220,7 +220,7 @@ static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, s
UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax - 2, &rectf.xmax, &rectf.ymax);
/* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* get beztriple editing/validation funcs */
@@ -262,7 +262,7 @@ static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, s
{
/* loop over data selecting */
switch (ale->type) {
-#if 0 /* XXXX: Keyframes are not currently shown here */
+#if 0 /* XXX: Keyframes are not currently shown here */
case ANIMTYPE_GPDATABLOCK:
{
bGPdata *gpd = ale->data;
@@ -401,7 +401,7 @@ static void region_select_action_keys(bAnimContext *ac, const rctf *rectf_view,
UI_view2d_region_to_view_rctf(v2d, rectf_view, &rectf);
/* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* get beztriple editing/validation funcs */
@@ -466,6 +466,7 @@ static void region_select_action_keys(bAnimContext *ac, const rctf *rectf_view,
{
/* loop over data selecting */
switch (ale->type) {
+#if 0 /* XXX: Keyframes are not currently shown here */
case ANIMTYPE_GPDATABLOCK:
{
bGPdata *gpd = ale->data;
@@ -475,6 +476,7 @@ static void region_select_action_keys(bAnimContext *ac, const rctf *rectf_view,
}
break;
}
+#endif
case ANIMTYPE_GPLAYER:
{
ED_gplayer_frames_select_region(&ked, ale->data, mode, selectmode);
@@ -718,8 +720,6 @@ static void columnselect_action_keys(bAnimContext *ac, short mode)
KeyframeEditFunc select_cb, ok_cb;
KeyframeEditData ked = {{NULL}};
- /* initialize keyframe editing data */
-
/* build list of columns */
switch (mode) {
case ACTKEYS_COLUMNSEL_KEYS: /* list of selected keys */
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index 60b6bd0cd0b..2f85b915813 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -62,6 +62,7 @@
#include "ED_space_api.h"
#include "ED_sound.h"
#include "ED_uvedit.h"
+#include "ED_lattice.h"
#include "ED_mball.h"
#include "ED_logic.h"
#include "ED_clip.h"
@@ -109,6 +110,7 @@ void ED_spacetypes_init(void)
ED_operatortypes_animchannels();
ED_operatortypes_gpencil();
ED_operatortypes_object();
+ ED_operatortypes_lattice();
ED_operatortypes_mesh();
ED_operatortypes_sculpt();
ED_operatortypes_uvedit();
@@ -198,7 +200,8 @@ void ED_spacetypes_keymap(wmKeyConfig *keyconf)
ED_keymap_anim(keyconf);
ED_keymap_animchannels(keyconf);
ED_keymap_gpencil(keyconf);
- ED_keymap_object(keyconf); /* defines lattice also */
+ ED_keymap_object(keyconf);
+ ED_keymap_lattice(keyconf);
ED_keymap_mesh(keyconf);
ED_keymap_uvedit(keyconf);
ED_keymap_curve(keyconf);
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index fc1b6877f5e..2a703ebb46c 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -51,7 +51,7 @@
#include "WM_types.h"
#include "ED_screen.h"
-#include "ED_util.h"
+#include "ED_undo.h"
#include "RNA_access.h"
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 036db87e846..809480baece 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -45,7 +45,7 @@
#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -351,18 +351,20 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext *
workspace = (WorkSpace *)workspace;
}
- if (!scene)
+ if (!scene) {
scene = CTX_data_scene(C);
+ }
- if (!pinid || GS(pinid->name) == ID_SCE) {
- wrld = scene->world;
+ const ID_Type id_type = pinid != NULL ? GS(pinid->name) : -1;
+ if (!pinid || ELEM(id_type, ID_SCE, ID_WS)) {
brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
- linestyle = BKE_linestyle_active_from_scene(scene);
- }
- else if (!pinid || GS(pinid->name) == ID_WS) {
- if (!workspace) {
+
+ if (workspace == NULL) {
+ wrld = scene->world;
+ linestyle = BKE_linestyle_active_from_scene(scene);
workspace = CTX_wm_workspace(C);
}
+
ViewLayer *view_layer = BKE_view_layer_from_workspace_get(scene, workspace);
ob = OBACT(view_layer);
}
@@ -480,7 +482,7 @@ void buttons_texture_context_compute(const bContext *C, SpaceButs *sbuts)
}
else {
/* set one user as active based on active index */
- if (ct->index >= BLI_listbase_count_ex(&ct->users, ct->index + 1))
+ if (ct->index >= BLI_listbase_count_at_most(&ct->users, ct->index + 1))
ct->index = 0;
ct->user = BLI_findlink(&ct->users, ct->index);
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index 09d225fc1b8..5962bfe33f3 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -157,7 +157,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking);
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
/* cache background */
ED_region_cache_draw_background(ar);
@@ -314,7 +314,7 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
/* checkerboard for case alpha */
if (ibuf->planes == 32) {
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
imm_draw_box_checker_2d(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y);
}
@@ -1126,11 +1126,12 @@ static void draw_plane_marker_image(Scene *scene,
if (plane_track->image_opacity != 1.0f || ibuf->planes == 32) {
transparent = true;
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
glGenTextures(1, (GLuint *)&texid);
+ glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -1148,7 +1149,7 @@ static void draw_plane_marker_image(Scene *scene,
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
immUniformColor4f(1.0f, 1.0f, 1.0f, plane_track->image_opacity);
- immUniform1i("image", GL_TEXTURE0);
+ immUniform1i("image", 0);
immBegin(GWN_PRIM_TRI_FAN, 4);
diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c
index 1504ce1a7ba..d2a7244eded 100644
--- a/source/blender/editors/space_clip/clip_toolbar.c
+++ b/source/blender/editors/space_clip/clip_toolbar.c
@@ -49,7 +49,7 @@
#include "WM_api.h"
#include "ED_screen.h"
-#include "ED_util.h"
+#include "ED_undo.h"
#include "UI_interface.h"
#include "UI_resources.h"
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index 7f9d9bf577c..9f79e8ffd6b 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -302,7 +302,7 @@ void clip_draw_sfra_efra(View2D *v2d, Scene *scene)
UI_view2d_view_ortho(v2d);
/* currently clip editor supposes that editing clip length is equal to scene frame range */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index 4ca2b54eaaf..f2bf817f502 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -1859,7 +1859,7 @@ static bool is_track_clean(MovieTrackingTrack *track, int frames, int del)
}
}
- if (count == 0) {
+ if (del && count == 0) {
ok = 0;
}
diff --git a/source/blender/editors/space_clip/tracking_ops_orient.c b/source/blender/editors/space_clip/tracking_ops_orient.c
index 8e3871836e4..583beef5001 100644
--- a/source/blender/editors/space_clip/tracking_ops_orient.c
+++ b/source/blender/editors/space_clip/tracking_ops_orient.c
@@ -42,7 +42,6 @@
#include "BKE_context.h"
#include "BKE_constraint.h"
#include "BKE_tracking.h"
-#include "BKE_global.h"
#include "BKE_layer.h"
#include "BKE_object.h"
#include "BKE_report.h"
@@ -71,7 +70,7 @@ static Object *get_camera_with_movieclip(Scene *scene, MovieClip *clip)
return camera;
}
- FOREACH_SCENE_OBJECT(scene, ob)
+ FOREACH_SCENE_OBJECT_BEGIN(scene, ob)
{
if (ob->type == OB_CAMERA) {
if (BKE_object_movieclip_get(scene, ob, false) == clip) {
@@ -80,7 +79,7 @@ static Object *get_camera_with_movieclip(Scene *scene, MovieClip *clip)
}
}
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
return camera;
}
diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c
index 4ee85ace271..ecbc1f5ae1e 100644
--- a/source/blender/editors/space_clip/tracking_select.c
+++ b/source/blender/editors/space_clip/tracking_select.c
@@ -37,7 +37,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_rect.h"
-#include "BLI_lasso.h"
+#include "BLI_lasso_2d.h"
#include "BKE_context.h"
#include "BKE_tracking.h"
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index c1e298c426f..043f32c56e7 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -52,6 +52,8 @@
#include "BLT_translation.h"
+#include "BLF_api.h"
+
#include "IMB_imbuf_types.h"
#include "DNA_userdef_types.h"
@@ -375,7 +377,7 @@ static void file_draw_preview(
xco = sx + (int)dx;
yco = sy - layout->prv_h + (int)dy;
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
/* shadow */
if (use_dropshadow) {
@@ -607,6 +609,8 @@ void file_draw_list(const bContext *C, ARegion *ar)
}
}
+ BLF_batch_draw_begin();
+
for (i = offset; (i < numfiles) && (i < offset + numfiles_layout); i++) {
unsigned int file_selflag;
char path[FILE_MAX_LIBEXTRA];
@@ -626,7 +630,7 @@ 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;
- BLI_assert(i > 0 || FILENAME_IS_CURRPAR(file->relpath));
+ 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);
}
@@ -736,6 +740,8 @@ void file_draw_list(const bContext *C, ARegion *ar)
}
}
+ BLF_batch_draw_end();
+
UI_block_end(C, block);
UI_block_draw(C, block);
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 3f26604c23a..0fe51ea1c70 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -189,6 +189,9 @@ static SpaceLink *file_duplicate(SpaceLink *sl)
/* clear or remove stuff from old */
sfilen->op = NULL; /* file window doesn't own operators */
+ sfilen->previews_timer = NULL;
+ sfilen->smoothscroll_timer = NULL;
+
if (sfileo->params) {
sfilen->files = filelist_new(sfileo->params->type);
sfilen->params = MEM_dupallocN(sfileo->params);
@@ -289,8 +292,9 @@ static void file_refresh(const bContext *C, ScrArea *sa)
file_tools_region(sa);
ED_area_initialize(wm, CTX_wm_window(C), sa);
- ED_area_tag_redraw(sa);
}
+
+ ED_area_tag_redraw(sa);
}
static void file_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene),
@@ -304,16 +308,13 @@ static void file_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Sce
switch (wmn->data) {
case ND_SPACE_FILE_LIST:
ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
break;
case ND_SPACE_FILE_PARAMS:
ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
break;
case ND_SPACE_FILE_PREVIEW:
if (sfile->files && filelist_cache_previews_update(sfile->files)) {
ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
}
break;
}
@@ -372,6 +373,15 @@ static void file_main_region_message_subscribe(
.notify = ED_area_do_msg_notify_tag_refresh,
};
+ /* SpaceFile itself. */
+ {
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_SpaceFileBrowser, sfile, &ptr);
+
+ /* All properties for this space type. */
+ WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_area_tag_refresh, __func__);
+ }
+
/* FileSelectParams */
{
PointerRNA ptr;
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index 49f498b3419..c79652795ac 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -64,7 +64,7 @@
#include "ED_anim_api.h"
#include "ED_keyframing.h"
#include "ED_screen.h"
-#include "ED_util.h"
+#include "ED_undo.h"
#include "UI_interface.h"
#include "UI_resources.h"
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index d917e3b85a2..26a3f110d36 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -323,8 +323,12 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
{
int sel, b;
- unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+ immBeginAtMost(GWN_PRIM_LINES, 4 * 2 * fcu->totvert);
/* slightly hacky, but we want to draw unselected points before selected ones
* so that selected points are clearly visible
@@ -334,7 +338,7 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
int basecol = (sel) ? TH_HANDLE_SEL_FREE : TH_HANDLE_FREE;
const float *fp;
unsigned char col[4];
-
+
for (b = 0; b < fcu->totvert; b++, prevbezt = bezt, bezt++) {
/* if only selected keyframes can get their handles shown,
* check that keyframe is selected
@@ -352,24 +356,20 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
UI_GetThemeColor3ubv(basecol + bezt->h1, col);
col[3] = fcurve_display_alpha(fcu) * 255;
- immUniformColor4ubv(col);
-
- immBegin(GWN_PRIM_LINES, 2);
+ immAttrib4ubv(color, col);
immVertex2fv(pos, fp);
+ immAttrib4ubv(color, col);
immVertex2fv(pos, fp + 3);
- immEnd();
}
/* only draw second handle if this segment is bezier */
if (bezt->ipo == BEZT_IPO_BEZ) {
UI_GetThemeColor3ubv(basecol + bezt->h2, col);
col[3] = fcurve_display_alpha(fcu) * 255;
- immUniformColor4ubv(col);
-
- immBegin(GWN_PRIM_LINES, 2);
+ immAttrib4ubv(color, col);
immVertex2fv(pos, fp + 3);
+ immAttrib4ubv(color, col);
immVertex2fv(pos, fp + 6);
- immEnd();
}
}
else {
@@ -380,12 +380,10 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
fp = bezt->vec[0];
UI_GetThemeColor3ubv(basecol + bezt->h1, col);
col[3] = fcurve_display_alpha(fcu) * 255;
- immUniformColor4ubv(col);
-
- immBegin(GWN_PRIM_LINES, 2);
+ immAttrib4ubv(color, col);
immVertex2fv(pos, fp);
+ immAttrib4ubv(color, col);
immVertex2fv(pos, fp + 3);
- immEnd();
}
/* only draw second handle if this segment is bezier, and selection is ok */
@@ -395,17 +393,16 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
fp = bezt->vec[1];
UI_GetThemeColor3ubv(basecol + bezt->h2, col);
col[3] = fcurve_display_alpha(fcu) * 255;
- immUniformColor4ubv(col);
-
- immBegin(GWN_PRIM_LINES, 2);
+ immAttrib4ubv(color, col);
immVertex2fv(pos, fp);
+ immAttrib4ubv(color, col);
immVertex2fv(pos, fp + 3);
- immEnd();
}
}
}
}
+ immEnd();
immUnbindProgram();
}
@@ -1232,7 +1229,7 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
y = (float)ACHANNEL_FIRST(ac);
/* set blending again, as may not be set in previous step */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) {
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index ce6ce802a5b..29e3f99e1d4 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -2824,7 +2824,7 @@ void GRAPH_OT_driver_delete_invalid(wmOperatorType *ot)
/* identifiers */
ot->name = "Delete Invalid Drivers";
ot->idname = "GRAPH_OT_driver_delete_invalid";
- ot->description = "Deletes all visible drivers considered invalid";
+ ot->description = "Delete all visible drivers considered invalid";
/* api callbacks */
ot->exec = graph_driver_delete_invalid_exec;
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 392db4ef4b5..0b7ce7d7310 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -37,7 +37,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_lasso.h"
+#include "BLI_lasso_2d.h"
#include "DNA_anim_types.h"
#include "DNA_screen_types.h"
diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c
index 0e56dc817e4..907f346c931 100644
--- a/source/blender/editors/space_graph/graph_utils.c
+++ b/source/blender/editors/space_graph/graph_utils.c
@@ -171,8 +171,8 @@ int graphop_editable_keyframes_poll(bContext *C)
/* editable curves must fulfill the following criteria:
* - it has bezier keyframes
- * - it must not be protected from editing (this is already checked for with the foredit flag
- * - F-Curve modifiers do not interfere with the result too much
+ * - it must not be protected from editing (this is already checked for with the edit flag
+ * - F-Curve modifiers do not interfere with the result too much
* (i.e. the modifier-control drawing check returns false)
*/
if (fcu->bezt == NULL)
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index 4b89c8db9e6..a424084f6b1 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -699,13 +699,14 @@ static void graph_refresh(const bContext *C, ScrArea *sa)
static void graph_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
{
SpaceIpo *sgraph = (SpaceIpo *)slink;
-
- if (!ELEM(GS(old_id->name), ID_GR)) {
- return;
- }
-
- if (sgraph->ads && (ID *)sgraph->ads->filter_grp == old_id) {
- sgraph->ads->filter_grp = (Group *)new_id;
+
+ if (sgraph->ads) {
+ if ((ID *)sgraph->ads->filter_grp == old_id) {
+ sgraph->ads->filter_grp = (Group *)new_id;
+ }
+ if ((ID *)sgraph->ads->source == old_id) {
+ sgraph->ads->source = new_id;
+ }
}
}
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 20f9658020d..c105f40f1d6 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -762,7 +762,7 @@ static void uiblock_layer_pass_buttons(
}
/* view */
- if (BLI_listbase_count_ex(&rr->views, 2) > 1 &&
+ if (BLI_listbase_count_at_most(&rr->views, 2) > 1 &&
((!show_stereo) || (!RE_RenderResult_is_stereo(rr))))
{
rview = BLI_findlink(&rr->views, iuser->view);
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 23c4fbbe45e..43d5348da3e 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -170,7 +170,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
float hue = 0, sat = 0, val = 0, lum = 0, u = 0, v = 0;
float col[4], finalcol[4];
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
@@ -482,8 +482,6 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar,
{
int x, y;
- glaDefine2DArea(&ar->winrct);
-
/* find window pixel coordinates of origin */
UI_view2d_view_to_region(&ar->v2d, fx, fy, &x, &y);
@@ -506,7 +504,7 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar,
imm_draw_box_checker_2d(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy);
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
/* If RGBA display with color management */
@@ -733,7 +731,7 @@ static void draw_image_paint_helpers(const bContext *C, ARegion *ar, Scene *scen
}
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
immDrawPixelsTex(&state, x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer, zoomx, zoomy, col);
@@ -794,7 +792,7 @@ void draw_image_main(const bContext *C, ARegion *ar)
* other images are not modifying in such a way so they does not require
* lock (sergey)
*/
- BLI_lock_thread(LOCK_DRAW_IMAGE);
+ BLI_thread_lock(LOCK_DRAW_IMAGE);
}
if (show_stereo3d) {
@@ -838,7 +836,7 @@ void draw_image_main(const bContext *C, ARegion *ar)
draw_image_paint_helpers(C, ar, scene, zoomx, zoomy);
if (show_viewer) {
- BLI_unlock_thread(LOCK_DRAW_IMAGE);
+ BLI_thread_unlock(LOCK_DRAW_IMAGE);
}
/* render info */
@@ -879,7 +877,7 @@ void draw_image_cache(const bContext *C, ARegion *ar)
}
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
/* Draw cache background. */
ED_region_cache_draw_background(ar);
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index 587689eda78..c719af9e0e2 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -44,6 +44,8 @@
#include "IMB_imbuf_types.h"
+#include "DEG_depsgraph.h"
+
#include "ED_image.h" /* own include */
#include "ED_mesh.h"
#include "ED_screen.h"
@@ -374,7 +376,7 @@ bool ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
}
/* matches clip function */
-bool ED_space_image_check_show_maskedit(ViewLayer *view_layer, SpaceImage *sima)
+bool ED_space_image_check_show_maskedit(SpaceImage *sima, ViewLayer *view_layer)
{
/* check editmode - this is reserved for UV editing */
Object *ob = OBACT(view_layer);
@@ -391,7 +393,7 @@ int ED_space_image_maskedit_poll(bContext *C)
if (sima) {
ViewLayer *view_layer = CTX_data_view_layer(C);
- return ED_space_image_check_show_maskedit(view_layer, sima);
+ return ED_space_image_check_show_maskedit(sima, view_layer);
}
return false;
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 6c0ab33dd2c..9162b8b76a9 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -279,8 +279,9 @@ static int space_image_main_area_not_uv_brush_poll(bContext *C)
Scene *scene = CTX_data_scene(C);
ToolSettings *toolsettings = scene->toolsettings;
- if (sima && !toolsettings->uvsculpt && !scene->obedit)
+ if (sima && !toolsettings->uvsculpt && (CTX_data_edit_object(C) == NULL)) {
return 1;
+ }
return 0;
}
@@ -814,7 +815,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
}
- else if (ED_space_image_check_show_maskedit(view_layer, sima)) {
+ else if (ED_space_image_check_show_maskedit(sima, view_layer)) {
if (!ED_mask_selected_minmax(C, min, max)) {
return OPERATOR_CANCELLED;
}
@@ -1857,7 +1858,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
/* we need renderresult for exr and rendered multiview */
scene = CTX_data_scene(C);
rr = BKE_image_acquire_renderresult(scene, ima);
- bool is_mono = rr ? BLI_listbase_count_ex(&rr->views, 2) < 2 : BLI_listbase_count_ex(&ima->views, 2) < 2;
+ bool is_mono = rr ? BLI_listbase_count_at_most(&rr->views, 2) < 2 : BLI_listbase_count_at_most(&ima->views, 2) < 2;
bool is_exr_rr = rr && ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER) && RE_HasFloatPixels(rr);
/* error handling */
@@ -2458,7 +2459,7 @@ static int image_new_exec(bContext *C, wmOperator *op)
SpaceImage *sima_other = (SpaceImage *)sl;
if (!sima_other->pin) {
- ED_space_image_set(sima_other, scene, scene->obedit, ima);
+ ED_space_image_set(sima_other, scene, obedit, ima);
}
}
}
@@ -2623,8 +2624,7 @@ static int image_invert_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
if (support_undo) {
- ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
- ED_image_undo_restore, ED_image_undo_free, NULL);
+ ED_image_undo_push_begin(op->type->name);
/* not strictly needed, because we only imapaint_dirty_region to invalidate all tiles
* but better do this right in case someone copies this for a tool that uses partial redraw better */
ED_imapaint_clear_partial_redraw();
@@ -2665,8 +2665,9 @@ static int image_invert_exec(bContext *C, wmOperator *op)
if (ibuf->mipmap[0])
ibuf->userflags |= IB_MIPMAP_INVALID;
- if (support_undo)
- ED_undo_paint_push_end(UNDO_PAINT_IMAGE);
+ if (support_undo) {
+ ED_image_undo_push_end();
+ }
/* force GPU reupload, all image is invalid */
GPU_free_image(ima);
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index a89ae2b869a..54037059cc3 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -800,14 +800,14 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
/* ED_space_image_get* will acquire image buffer which requires
* lock here by the same reason why lock is needed in draw_image_main
*/
- BLI_lock_thread(LOCK_DRAW_IMAGE);
+ BLI_thread_lock(LOCK_DRAW_IMAGE);
}
ED_space_image_get_size(sima, &width, &height);
ED_space_image_get_aspect(sima, &aspx, &aspy);
if (show_viewer)
- BLI_unlock_thread(LOCK_DRAW_IMAGE);
+ BLI_thread_unlock(LOCK_DRAW_IMAGE);
ED_mask_draw_region(mask, ar,
sima->mask_info.draw_flag,
diff --git a/source/blender/editors/space_info/info_report.c b/source/blender/editors/space_info/info_report.c
index 31df9b199ea..a6b3dad239c 100644
--- a/source/blender/editors/space_info/info_report.c
+++ b/source/blender/editors/space_info/info_report.c
@@ -133,9 +133,6 @@ static int select_report_pick_invoke(bContext *C, wmOperator *op, const wmEvent
ReportList *reports = CTX_wm_reports(C);
Report *report;
- /* uses opengl */
- wmSubWindowSet(CTX_wm_window(C), ar->swinid);
-
report = info_text_pick(sinfo, ar, reports, event->mval[1]);
RNA_int_set(op->ptr, "report_index", BLI_findindex(&reports->list, report));
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 3cf833756ef..c7d4fa1465b 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -53,6 +53,7 @@
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_editmesh.h"
+#include "BKE_object.h"
#include "ED_info.h"
#include "ED_armature.h"
@@ -365,28 +366,30 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
}
}
-static bool stats_is_object_dynamic_topology_sculpt(Object *ob)
+static bool stats_is_object_dynamic_topology_sculpt(Object *ob, const eObjectMode object_mode)
{
- return (ob && (ob->mode & OB_MODE_SCULPT) &&
+ return (ob &&
+ (object_mode & OB_MODE_SCULPT) &&
ob->sculpt && ob->sculpt->bm);
}
/* Statistics displayed in info header. Called regularly on scene changes. */
-static void stats_update(Scene *scene, ViewLayer *view_layer)
+static void stats_update(ViewLayer *view_layer)
{
SceneStats stats = {0};
- Object *ob = (view_layer->basact) ? view_layer->basact->object : NULL;
+ Object *ob = OBACT(view_layer);
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
Base *base;
-
- if (scene->obedit) {
+
+ if (obedit) {
/* Edit Mode */
- stats_object_edit(scene->obedit, &stats);
+ stats_object_edit(ob, &stats);
}
else if (ob && (ob->mode & OB_MODE_POSE)) {
/* Pose Mode */
stats_object_pose(ob, &stats);
}
- else if (stats_is_object_dynamic_topology_sculpt(ob)) {
+ else if (ob && stats_is_object_dynamic_topology_sculpt(ob, ob->mode)) {
/* Dynamic-topology sculpt mode */
stats_object_sculpt_dynamic_topology(ob, &stats);
}
@@ -405,12 +408,14 @@ static void stats_update(Scene *scene, ViewLayer *view_layer)
*(view_layer->stats) = stats;
}
-static void stats_string(Scene *scene, ViewLayer *view_layer)
+static void stats_string(ViewLayer *view_layer)
{
#define MAX_INFO_MEM_LEN 64
SceneStats *stats = view_layer->stats;
SceneStatsFmt stats_fmt;
- Object *ob = (view_layer->basact) ? view_layer->basact->object : NULL;
+ Object *ob = OBACT(view_layer);
+ Object *obedit = OBEDIT_FROM_OBACT(ob);
+ eObjectMode object_mode = ob ? ob->mode : OB_MODE_OBJECT;
uintptr_t mem_in_use, mmap_in_use;
char memstr[MAX_INFO_MEM_LEN];
char gpumemstr[MAX_INFO_MEM_LEN] = "";
@@ -471,17 +476,17 @@ static void stats_string(Scene *scene, ViewLayer *view_layer)
ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, "%s | ", versionstr);
- if (scene->obedit) {
- if (BKE_keyblock_from_object(scene->obedit))
+ if (obedit) {
+ if (BKE_keyblock_from_object(obedit))
ofs += BLI_strncpy_rlen(s + ofs, IFACE_("(Key) "), MAX_INFO_LEN - ofs);
- if (scene->obedit->type == OB_MESH) {
+ if (obedit->type == OB_MESH) {
ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs,
IFACE_("Verts:%s/%s | Edges:%s/%s | Faces:%s/%s | Tris:%s"),
stats_fmt.totvertsel, stats_fmt.totvert, stats_fmt.totedgesel, stats_fmt.totedge,
stats_fmt.totfacesel, stats_fmt.totface, stats_fmt.tottri);
}
- else if (scene->obedit->type == OB_ARMATURE) {
+ else if (obedit->type == OB_ARMATURE) {
ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s/%s | Bones:%s/%s"), stats_fmt.totvertsel,
stats_fmt.totvert, stats_fmt.totbonesel, stats_fmt.totbone);
}
@@ -493,11 +498,11 @@ static void stats_string(Scene *scene, ViewLayer *view_layer)
ofs += BLI_strncpy_rlen(s + ofs, memstr, MAX_INFO_LEN - ofs);
ofs += BLI_strncpy_rlen(s + ofs, gpumemstr, MAX_INFO_LEN - ofs);
}
- else if (ob && (ob->mode & OB_MODE_POSE)) {
+ else if (ob && (object_mode & OB_MODE_POSE)) {
ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Bones:%s/%s %s%s"),
stats_fmt.totbonesel, stats_fmt.totbone, memstr, gpumemstr);
}
- else if (stats_is_object_dynamic_topology_sculpt(ob)) {
+ else if (stats_is_object_dynamic_topology_sculpt(ob, object_mode)) {
ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s | Tris:%s%s"), stats_fmt.totvert,
stats_fmt.tottri, gpumemstr);
}
@@ -525,12 +530,11 @@ void ED_info_stats_clear(ViewLayer *view_layer)
}
}
-const char *ED_info_stats_string(Scene *scene, ViewLayer *view_layer)
+const char *ED_info_stats_string(Scene *UNUSED(scene), ViewLayer *view_layer)
{
if (!view_layer->stats) {
- stats_update(scene, view_layer);
+ stats_update(view_layer);
}
- stats_string(scene, view_layer);
-
+ stats_string(view_layer);
return view_layer->stats->infostr;
}
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index 3eb0158e7b5..3f35cadd820 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -82,7 +82,7 @@ static void console_draw_sel(const char *str, const int sel[2], const int xy[2],
const int end = txt_utf8_offset_to_column(str, min_ii(sel[1], str_len_draw));
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index c6fd70a60dd..9bdc92f98ab 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -56,7 +56,7 @@
#include "BKE_main.h"
#include "BKE_sca.h"
-#include "ED_util.h"
+#include "ED_undo.h"
#include "BLT_translation.h"
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index 89bf57fdb6c..1cc3d5142f5 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -594,12 +594,12 @@ bool nlaedit_add_tracks_existing(bAnimContext *ac, bool above_sel)
*/
if (above_sel) {
/* just add a new one above this one */
- add_nlatrack(adt, nlt);
+ BKE_nlatrack_add(adt, nlt);
added = true;
}
else if ((lastAdt == NULL) || (adt != lastAdt)) {
/* add one track to the top of the owning AnimData's stack, then don't add anymore to this stack */
- add_nlatrack(adt, NULL);
+ BKE_nlatrack_add(adt, NULL);
lastAdt = adt;
added = true;
}
@@ -634,7 +634,7 @@ bool nlaedit_add_tracks_empty(bAnimContext *ac)
/* ensure it is empty */
if (BLI_listbase_is_empty(&adt->nla_tracks)) {
/* add new track to this AnimData block then */
- add_nlatrack(adt, NULL);
+ BKE_nlatrack_add(adt, NULL);
added = true;
}
}
@@ -729,7 +729,7 @@ static int nlaedit_delete_tracks_exec(bContext *C, wmOperator *UNUSED(op))
adt->flag &= ~ADT_NLA_SOLO_TRACK;
/* call delete on this track - deletes all strips too */
- free_nlatrack(&adt->nla_tracks, nlt);
+ BKE_nlatrack_free(&adt->nla_tracks, nlt);
}
}
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index cb20b76a3ee..a7773aaaed5 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -316,18 +316,20 @@ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, uns
float cfra;
/* plot the curve (over the strip's main region) */
- immBegin(GWN_PRIM_LINE_STRIP, abs((int)(strip->end - strip->start) + 1));
+ if (fcu) {
+ immBegin(GWN_PRIM_LINE_STRIP, abs((int)(strip->end - strip->start) + 1));
- /* sample at 1 frame intervals, and draw
- * - min y-val is yminc, max is y-maxc, so clamp in those regions
- */
- for (cfra = strip->start; cfra <= strip->end; cfra += 1.0f) {
- float y = evaluate_fcurve(fcu, cfra); /* assume this to be in 0-1 range */
- CLAMP(y, 0.0f, 1.0f);
- immVertex2f(pos, cfra, ((y * yheight) + yminc));
- }
+ /* sample at 1 frame intervals, and draw
+ * - min y-val is yminc, max is y-maxc, so clamp in those regions
+ */
+ for (cfra = strip->start; cfra <= strip->end; cfra += 1.0f) {
+ float y = evaluate_fcurve(fcu, cfra); /* assume this to be in 0-1 range */
+ CLAMP(y, 0.0f, 1.0f);
+ immVertex2f(pos, cfra, ((y * yheight) + yminc));
+ }
- immEnd();
+ immEnd();
+ }
}
else {
/* use blend in/out values only if both aren't zero */
@@ -408,7 +410,7 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
*/
if ((strip->extendmode != NLASTRIP_EXTEND_NOTHING) && (non_solo == 0)) {
/* enable transparency... */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
switch (strip->extendmode) {
@@ -709,7 +711,7 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
/* just draw a semi-shaded rect spanning the width of the viewable area if there's data,
* and a second darker rect within which we draw keyframe indicator dots if there's data
*/
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
/* get colors for drawing */
@@ -826,7 +828,7 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
y = (float)(-NLACHANNEL_HEIGHT(snla));
/* set blending again, as may not be set in previous step */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
/* loop through channels, and set up drawing depending on their type */
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index 31524f8450a..c86e9872c0a 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -645,7 +645,7 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op)
}
/* create a new strip, and offset it to start on the current frame */
- strip = add_nlastrip(act);
+ strip = BKE_nlastrip_new(act);
strip->end += (cfra - strip->start);
strip->start = cfra;
@@ -655,7 +655,7 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op)
/* trying to add to the current failed (no space),
* so add a new track to the stack, and add to that...
*/
- nlt = add_nlatrack(adt, NULL);
+ nlt = BKE_nlatrack_add(adt, NULL);
BKE_nlatrack_add_strip(nlt, strip);
}
@@ -858,7 +858,7 @@ static int nlaedit_add_sound_exec(bContext *C, wmOperator *UNUSED(op))
continue;
/* create a new strip, and offset it to start on the current frame */
- strip = add_nla_soundstrip(ac.scene, ob->data);
+ strip = BKE_nla_add_soundstrip(ac.scene, ob->data);
strip->start += cfra;
strip->end += cfra;
@@ -868,7 +868,7 @@ static int nlaedit_add_sound_exec(bContext *C, wmOperator *UNUSED(op))
/* trying to add to the current failed (no space),
* so add a new track to the stack, and add to that...
*/
- nlt = add_nlatrack(adt, NULL);
+ nlt = BKE_nlatrack_add(adt, NULL);
BKE_nlatrack_add_strip(nlt, strip);
}
@@ -1057,7 +1057,7 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
/* if selected, split the strip at its midpoint */
if (strip->flag & NLASTRIP_FLAG_SELECT) {
/* make a copy (assume that this is possible) */
- nstrip = copy_nlastrip(strip, linked);
+ nstrip = BKE_nlastrip_copy(strip, linked);
/* in case there's no space in the track above, or we haven't got a reference to it yet, try adding */
if (BKE_nlatrack_add_strip(nlt->next, nstrip) == 0) {
@@ -1065,7 +1065,7 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
* - if the current one is the last one, nlt->next will be NULL, which defaults to adding
* at the top of the stack anyway...
*/
- track = add_nlatrack(adt, nlt->next);
+ track = BKE_nlatrack_add(adt, nlt->next);
BKE_nlatrack_add_strip(track, nstrip);
}
@@ -1160,14 +1160,14 @@ static int nlaedit_delete_exec(bContext *C, wmOperator *UNUSED(op))
if (strip->flag & NLASTRIP_FLAG_SELECT) {
/* if a strip either side of this was a transition, delete those too */
if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION))
- free_nlastrip(&nlt->strips, strip->prev);
+ BKE_nlastrip_free(&nlt->strips, strip->prev);
if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) {
nstrip = nstrip->next;
- free_nlastrip(&nlt->strips, strip->next);
+ BKE_nlastrip_free(&nlt->strips, strip->next);
}
/* finally, delete this strip */
- free_nlastrip(&nlt->strips, strip);
+ BKE_nlastrip_free(&nlt->strips, strip);
}
}
}
@@ -1242,7 +1242,7 @@ static void nlaedit_split_strip_actclip(AnimData *adt, NlaTrack *nlt, NlaStrip *
/* make a copy (assume that this is possible) and append
* it immediately after the current strip
*/
- nstrip = copy_nlastrip(strip, true);
+ nstrip = BKE_nlastrip_copy(strip, true);
BLI_insertlinkafter(&nlt->strips, strip, nstrip);
/* set the endpoint of the first strip and the start of the new strip
@@ -1501,7 +1501,7 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op)
NlaStrip *mstrip = (NlaStrip *)nlt->strips.first;
if ((mstrip->flag & NLASTRIP_FLAG_TEMP_META) &&
- (BLI_listbase_count_ex(&mstrip->strips, 3) == 2))
+ (BLI_listbase_count_at_most(&mstrip->strips, 3) == 2))
{
/* remove this temp meta, so that we can see the strips inside */
BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
@@ -2186,7 +2186,7 @@ static int nlaedit_snap_exec(bContext *C, wmOperator *op)
/* in case there's no space in the current track, try adding */
if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
/* need to add a new track above the current one */
- track = add_nlatrack(adt, nlt);
+ track = BKE_nlatrack_add(adt, nlt);
BKE_nlatrack_add_strip(track, strip);
/* clear temp meta-strips on this new track, as we may not be able to get back to it */
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index f6068087f02..08ac7c8973e 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -517,13 +517,14 @@ static void nla_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scen
static void nla_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
{
SpaceNla *snla = (SpaceNla *)slink;
-
- if (!ELEM(GS(old_id->name), ID_GR)) {
- return;
- }
-
- if ((ID *)snla->ads->filter_grp == old_id) {
- snla->ads->filter_grp = (Group *)new_id;
+
+ if (snla->ads) {
+ if ((ID *)snla->ads->filter_grp == old_id) {
+ snla->ads->filter_grp = (Group *)new_id;
+ }
+ if ((ID *)snla->ads->source == old_id) {
+ snla->ads->source = new_id;
+ }
}
}
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 1bee2716e65..1cb9c57404a 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -53,6 +53,7 @@
#include "BIF_glutil.h"
#include "GPU_draw.h"
+#include "GPU_batch.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
@@ -986,7 +987,7 @@ static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRN
{
uiItemR(layout, ptr, "space", 0, "", 0);
- if (RNA_enum_get(ptr, "space") == SHD_NORMAL_MAP_TANGENT) {
+ if (RNA_enum_get(ptr, "space") == SHD_SPACE_TANGENT) {
PointerRNA obptr = CTX_data_pointer_get(C, "active_object");
if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
@@ -998,6 +999,11 @@ static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRN
}
}
+static void node_shader_buts_displacement(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "space", 0, "", 0);
+}
+
static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
uiLayout *split, *row;
@@ -1027,6 +1033,12 @@ static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), Point
uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
}
+static void node_shader_buts_principled(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "subsurface_method", 0, "", ICON_NONE);
+}
+
static void node_shader_buts_anisotropic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
@@ -1189,15 +1201,21 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_NORMAL_MAP:
ntype->draw_buttons = node_shader_buts_normal_map;
break;
+ case SH_NODE_DISPLACEMENT:
+ case SH_NODE_VECTOR_DISPLACEMENT:
+ ntype->draw_buttons = node_shader_buts_displacement;
+ break;
case SH_NODE_TANGENT:
ntype->draw_buttons = node_shader_buts_tangent;
break;
case SH_NODE_BSDF_GLOSSY:
case SH_NODE_BSDF_GLASS:
case SH_NODE_BSDF_REFRACTION:
- case SH_NODE_BSDF_PRINCIPLED:
ntype->draw_buttons = node_shader_buts_glossy;
break;
+ case SH_NODE_BSDF_PRINCIPLED:
+ ntype->draw_buttons = node_shader_buts_principled;
+ break;
case SH_NODE_BSDF_ANISOTROPIC:
ntype->draw_buttons = node_shader_buts_anisotropic;
break;
@@ -2999,7 +3017,7 @@ static const float std_node_socket_colors[][4] = {
{0.70, 0.65, 0.19, 1.0}, /* SOCK_BOOLEAN */
{0.0, 0.0, 0.0, 1.0}, /*__SOCK_MESH (deprecated) */
{0.06, 0.52, 0.15, 1.0}, /* SOCK_INT */
- {1.0, 1.0, 1.0, 1.0}, /* SOCK_STRING */
+ {0.39, 0.39, 0.39, 1.0}, /* SOCK_STRING */
};
/* common color callbacks for standard types */
@@ -3086,20 +3104,11 @@ static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr,
uiTemplateComponentMenu(layout, ptr, "default_value", text);
break;
case SOCK_RGBA:
- {
- uiLayout *row = uiLayoutRow(layout, false);
- uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
- /* draw the socket name right of the actual button */
- uiItemR(row, ptr, "default_value", 0, "", 0);
- uiItemL(row, text, 0);
- break;
- }
case SOCK_STRING:
{
- uiLayout *row = uiLayoutRow(layout, true);
- /* draw the socket name right of the actual button */
- uiItemR(row, ptr, "default_value", 0, "", 0);
+ uiLayout *row = uiLayoutSplit(layout, 0.5f, false);
uiItemL(row, text, 0);
+ uiItemR(row, ptr, "default_value", 0, "", 0);
break;
}
default:
@@ -3133,11 +3142,6 @@ static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout
uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0);
break;
}
- case SOCK_BOOLEAN:
- {
- uiItemR(layout, ptr, "default_value", 0, NULL, 0);
- break;
- }
case SOCK_VECTOR:
{
uiLayout *row;
@@ -3147,11 +3151,8 @@ static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout
uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0);
break;
}
+ case SOCK_BOOLEAN:
case SOCK_RGBA:
- {
- uiItemR(layout, ptr, "default_value", 0, NULL, 0);
- break;
- }
case SOCK_STRING:
{
uiItemR(layout, ptr, "default_value", 0, NULL, 0);
@@ -3205,8 +3206,6 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
gpuPushMatrix();
/* somehow the offset has to be calculated inverse */
-
- glaDefine2DArea(&ar->winrct);
wmOrtho2_region_pixelspace(ar);
x = (ar->winx - snode->zoom * ibuf->x) / 2 + snode->xof;
@@ -3239,7 +3238,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
}
else if (snode->flag & SNODE_USE_ALPHA) {
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom);
@@ -3294,11 +3293,10 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
BKE_image_release_ibuf(ima, ibuf, lock);
}
-
-/* if v2d not NULL, it clips and returns 0 if not visible */
-bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol)
+/* return quadratic beziers points for a given nodelink and clip if v2d is not NULL. */
+static bool node_link_bezier_handles(View2D *v2d, SpaceNode *snode, bNodeLink *link, float vec[4][2])
{
- float dist, vec[4][2];
+ float dist;
float deltax, deltay;
float cursor[2] = {0.0f, 0.0f};
int toreroute, fromreroute;
@@ -3366,13 +3364,23 @@ bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, flo
vec[2][0] = vec[3][0] - dist;
vec[2][1] = vec[3][1];
}
+
if (v2d && min_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax) {
- /* clipped */
+ return 0; /* clipped */
}
else if (v2d && max_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < v2d->cur.xmin) {
- /* clipped */
+ return 0; /* clipped */
}
- else {
+
+ return 1;
+}
+
+/* if v2d not NULL, it clips and returns 0 if not visible */
+bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol)
+{
+ float vec[4][2];
+
+ if (node_link_bezier_handles(v2d, snode, link, vec)) {
/* always do all three, to prevent data hanging around */
BKE_curve_forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0],
coord_array[0] + 0, resol, sizeof(float) * 2);
@@ -3384,135 +3392,242 @@ bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, flo
return 0;
}
+#define NODELINK_GROUP_SIZE 256
#define LINK_RESOL 24
-#define LINK_ARROW 12 /* position of arrow on the link, LINK_RESOL/2 */
-#define ARROW_SIZE (7 * UI_DPI_FAC)
-void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
- int th_col1, bool do_shaded, int th_col2, bool do_triple, int th_col3)
-{
- float coord_array[LINK_RESOL + 1][2];
-
- if (node_link_bezier_points(v2d, snode, link, coord_array, LINK_RESOL)) {
- float dist, spline_step = 0.0f;
- int i;
- int drawarrow;
- /* store current linewidth */
- float linew;
- float arrow[2], arrow1[2], arrow2[2];
- glGetFloatv(GL_LINE_WIDTH, &linew);
- unsigned int pos;
-
- /* we can reuse the dist variable here to increment the GL curve eval amount*/
- dist = 1.0f / (float)LINK_RESOL;
-
- glEnable(GL_LINE_SMOOTH);
-
- drawarrow = ((link->tonode && (link->tonode->type == NODE_REROUTE)) &&
- (link->fromnode && (link->fromnode->type == NODE_REROUTE)));
-
- if (drawarrow) {
- /* draw arrow in line segment LINK_ARROW */
- float d_xy[2], len;
-
- sub_v2_v2v2(d_xy, coord_array[LINK_ARROW], coord_array[LINK_ARROW - 1]);
- len = len_v2(d_xy);
- mul_v2_fl(d_xy, ARROW_SIZE / len);
- arrow1[0] = coord_array[LINK_ARROW][0] - d_xy[0] + d_xy[1];
- arrow1[1] = coord_array[LINK_ARROW][1] - d_xy[1] - d_xy[0];
- arrow2[0] = coord_array[LINK_ARROW][0] - d_xy[0] - d_xy[1];
- arrow2[1] = coord_array[LINK_ARROW][1] - d_xy[1] + d_xy[0];
- arrow[0] = coord_array[LINK_ARROW][0];
- arrow[1] = coord_array[LINK_ARROW][1];
+#define LINK_WIDTH (2.5f * UI_DPI_FAC)
+#define ARROW_SIZE (7 * UI_DPI_FAC)
+
+static float arrow_verts[3][2] = {{-1.0f, 1.0f}, {0.0f, 0.0f}, {-1.0f, -1.0f}};
+static float arrow_expand_axis[3][2] = {{0.7071f, 0.7071f}, {M_SQRT2, 0.0f}, {0.7071f, -0.7071f}};
+
+struct {
+ Gwn_Batch *batch; /* for batching line together */
+ Gwn_Batch *batch_single; /* for single line */
+ Gwn_VertBuf *inst_vbo;
+ unsigned int p0_id, p1_id, p2_id, p3_id;
+ unsigned int colid_id;
+ Gwn_VertBufRaw p0_step, p1_step, p2_step, p3_step;
+ Gwn_VertBufRaw colid_step;
+ unsigned int count;
+ bool enabled;
+} g_batch_link = {0};
+
+static void nodelink_batch_reset(void)
+{
+ GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p0_id, &g_batch_link.p0_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p1_id, &g_batch_link.p1_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p2_id, &g_batch_link.p2_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p3_id, &g_batch_link.p3_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.colid_id, &g_batch_link.colid_step);
+ g_batch_link.count = 0;
+}
+
+static void set_nodelink_vertex(
+ Gwn_VertBuf *vbo,
+ unsigned int uv_id, unsigned int pos_id, unsigned int exp_id, unsigned int v,
+ const unsigned char uv[2], const float pos[2], const float exp[2])
+{
+ GWN_vertbuf_attr_set(vbo, uv_id, v, uv);
+ GWN_vertbuf_attr_set(vbo, pos_id, v, pos);
+ GWN_vertbuf_attr_set(vbo, exp_id, v, exp);
+}
+
+static void nodelink_batch_init(void)
+{
+ Gwn_VertFormat format = {0};
+ unsigned int uv_id = GWN_vertformat_attr_add(&format, "uv", GWN_COMP_U8, 2, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ unsigned int pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int expand_id = GWN_vertformat_attr_add(&format, "expand", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STATIC);
+ int vcount = LINK_RESOL * 2; /* curve */
+ vcount += 2; /* restart strip */
+ vcount += 3*2; /* arrow */
+ vcount *= 2; /* shadow */
+ vcount += 2; /* restart strip */
+ GWN_vertbuf_data_alloc(vbo, vcount);
+ int v = 0;
+
+ for (int k = 0; k < 2; ++k) {
+ unsigned char uv[2] = {0, 0};
+ float pos[2] = {0.0f, 0.0f};
+ float exp[2] = {0.0f, 1.0f};
+
+ /* restart */
+ if (k == 1)
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+
+ /* curve strip */
+ for (int i = 0; i < LINK_RESOL; ++i) {
+ uv[0] = 255 * (i / (float)(LINK_RESOL-1));
+ uv[1] = 0;
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+ uv[1] = 255;
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
}
-
- if (do_triple || drawarrow || (!do_shaded)) {
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ /* restart */
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+
+ uv[0] = 127;
+ uv[1] = 0;
+ copy_v2_v2(pos, arrow_verts[0]);
+ copy_v2_v2(exp, arrow_expand_axis[0]);
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+ /* arrow */
+ for (int i = 0; i < 3; ++i) {
+ uv[1] = 0;
+ copy_v2_v2(pos, arrow_verts[i]);
+ copy_v2_v2(exp, arrow_expand_axis[i]);
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+
+ uv[1] = 255;
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
}
- if (do_triple) {
- immUniformThemeColorShadeAlpha(th_col3, -80, -120);
- glLineWidth(4.0f);
+ /* restart */
+ if (k == 0)
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+ }
- immBegin(GWN_PRIM_LINE_STRIP, (LINK_RESOL + 1));
+ g_batch_link.batch = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ gpu_batch_presets_register(g_batch_link.batch);
- for (i = 0; i <= LINK_RESOL; i++) {
- immVertex2fv(pos, coord_array[i]);
- }
+ g_batch_link.batch_single = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, 0);
+ gpu_batch_presets_register(g_batch_link.batch_single);
- immEnd();
+ /* Instances data */
+ Gwn_VertFormat format_inst = {0};
+ g_batch_link.p0_id = GWN_vertformat_attr_add(&format_inst, "P0", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ g_batch_link.p1_id = GWN_vertformat_attr_add(&format_inst, "P1", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ g_batch_link.p2_id = GWN_vertformat_attr_add(&format_inst, "P2", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ g_batch_link.p3_id = GWN_vertformat_attr_add(&format_inst, "P3", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ g_batch_link.colid_id = GWN_vertformat_attr_add(&format_inst, "colid_doarrow", GWN_COMP_U8, 4, GWN_FETCH_INT);
+ g_batch_link.inst_vbo = GWN_vertbuf_create_with_format_ex(&format_inst, GWN_USAGE_STREAM);
+ GWN_vertbuf_data_alloc(g_batch_link.inst_vbo, NODELINK_GROUP_SIZE); /* Alloc max count but only draw the range we need. */
- if (drawarrow) {
- immBegin(GWN_PRIM_LINE_STRIP, 3);
- immVertex2fv(pos, arrow1);
- immVertex2fv(pos, arrow);
- immVertex2fv(pos, arrow2);
- immEnd();
- }
- }
+ GWN_batch_instbuf_set(g_batch_link.batch, g_batch_link.inst_vbo, true);
- glLineWidth(1.5f);
+ nodelink_batch_reset();
+}
- if (drawarrow) {
- immUniformThemeColorBlend(th_col1, th_col2, 0.5f);
+static char nodelink_get_color_id(int th_col)
+{
+ switch (th_col) {
+ case TH_WIRE: return 1;
+ case TH_WIRE_INNER: return 2;
+ case TH_ACTIVE: return 3;
+ case TH_EDGE_SELECT: return 4;
+ case TH_REDALERT: return 5;
+ }
+ return 0;
+}
- immBegin(GWN_PRIM_LINE_STRIP, 3);
- immVertex2fv(pos, arrow1);
- immVertex2fv(pos, arrow);
- immVertex2fv(pos, arrow2);
- immEnd();
- }
+static void nodelink_batch_draw(SpaceNode *snode)
+{
+ if (g_batch_link.count == 0)
+ return;
- if (!do_shaded) {
- immUniformThemeColor(th_col1);
+ glEnable(GL_BLEND);
- immBegin(GWN_PRIM_LINE_STRIP, (LINK_RESOL + 1));
+ float colors[6][4] = {{0.0f}};
+ UI_GetThemeColor4fv(TH_WIRE_INNER, colors[nodelink_get_color_id(TH_WIRE_INNER)]);
+ UI_GetThemeColor4fv(TH_WIRE, colors[nodelink_get_color_id(TH_WIRE)]);
+ UI_GetThemeColor4fv(TH_ACTIVE, colors[nodelink_get_color_id(TH_ACTIVE)]);
+ UI_GetThemeColor4fv(TH_EDGE_SELECT, colors[nodelink_get_color_id(TH_EDGE_SELECT)]);
+ UI_GetThemeColor4fv(TH_REDALERT, colors[nodelink_get_color_id(TH_REDALERT)]);
- for (i = 0; i <= LINK_RESOL; i++) {
- immVertex2fv(pos, coord_array[i]);
- }
+ GWN_vertbuf_vertex_count_set(g_batch_link.inst_vbo, g_batch_link.count);
+ GWN_vertbuf_use(g_batch_link.inst_vbo); /* force update. */
- immEnd();
- }
+ GWN_batch_program_set_builtin(g_batch_link.batch, GPU_SHADER_2D_NODELINK_INST);
+ GWN_batch_uniform_4fv_array(g_batch_link.batch, "colors", 6, (float *)colors);
+ GWN_batch_uniform_1f(g_batch_link.batch, "expandSize", snode->aspect * LINK_WIDTH);
+ GWN_batch_uniform_1f(g_batch_link.batch, "arrowSize", ARROW_SIZE);
+ GWN_batch_draw(g_batch_link.batch);
- if (do_triple || drawarrow || (!do_shaded)) {
- immUnbindProgram();
- }
+ nodelink_batch_reset();
- if (do_shaded) {
- unsigned char col[3];
+ glDisable(GL_BLEND);
+}
+
+void nodelink_batch_start(SpaceNode *UNUSED(snode))
+{
+ g_batch_link.enabled = true;
+}
- Gwn_VertFormat *format = immVertexFormat();
- pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+void nodelink_batch_end(SpaceNode *snode)
+{
+ nodelink_batch_draw(snode);
+ g_batch_link.enabled = false;
+}
- immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+static void nodelink_batch_add_link(
+ SpaceNode *snode,
+ const float p0[2], const float p1[2], const float p2[2], const float p3[2],
+ int th_col1, int th_col2, int th_col3, bool drawarrow)
+{
+ /* Only allow these colors. If more is needed, you need to modify the shader accordingly. */
+ BLI_assert(ELEM(th_col1, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT));
+ BLI_assert(ELEM(th_col2, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT));
+ BLI_assert(ELEM(th_col3, TH_WIRE, -1));
- immBegin(GWN_PRIM_LINE_STRIP, (LINK_RESOL + 1));
+ g_batch_link.count++;
+ copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p0_step), p0);
+ copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p1_step), p1);
+ copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p2_step), p2);
+ copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p3_step), p3);
+ char *colid = GWN_vertbuf_raw_step(&g_batch_link.colid_step);
+ colid[0] = nodelink_get_color_id(th_col1);
+ colid[1] = nodelink_get_color_id(th_col2);
+ colid[2] = nodelink_get_color_id(th_col3);
+ colid[3] = drawarrow;
- for (i = 0; i <= LINK_RESOL; i++) {
- UI_GetThemeColorBlend3ubv(th_col1, th_col2, spline_step, col);
- immAttrib3ubv(color, col);
+ if (g_batch_link.count == NODELINK_GROUP_SIZE) {
+ nodelink_batch_draw(snode);
+ }
+}
- immVertex2fv(pos, coord_array[i]);
+/* don't do shadows if th_col3 is -1. */
+void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
+ int th_col1, int th_col2, int th_col3)
+{
+ float vec[4][2];
- spline_step += dist;
- }
+ if (node_link_bezier_handles(v2d, snode, link, vec)) {
+ int drawarrow = ((link->tonode && (link->tonode->type == NODE_REROUTE)) &&
+ (link->fromnode && (link->fromnode->type == NODE_REROUTE)));
- immEnd();
+ if (g_batch_link.batch == NULL) {
+ nodelink_batch_init();
+ }
- immUnbindProgram();
+ if (g_batch_link.enabled) {
+ /* Add link to batch. */
+ nodelink_batch_add_link(snode, vec[0], vec[1], vec[2], vec[3], th_col1, th_col2, th_col3, drawarrow);
+ }
+ else {
+ /* Draw single link. */
+ float colors[3][4] = {{0.0f}};
+ if (th_col3 != -1) {
+ UI_GetThemeColor4fv(th_col3, colors[0]);
+ }
+ UI_GetThemeColor4fv(th_col1, colors[1]);
+ UI_GetThemeColor4fv(th_col2, colors[2]);
+
+ Gwn_Batch *batch = g_batch_link.batch_single;
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_NODELINK);
+ GWN_batch_uniform_2fv_array(batch, "bezierPts", 4, (float *)vec);
+ GWN_batch_uniform_4fv_array(batch, "colors", 3, (float *)colors);
+ GWN_batch_uniform_1f(batch, "expandSize", snode->aspect * LINK_WIDTH);
+ GWN_batch_uniform_1f(batch, "arrowSize", ARROW_SIZE);
+ GWN_batch_uniform_1i(batch, "doArrow", drawarrow);
+ GWN_batch_draw(batch);
}
-
- glDisable(GL_LINE_SMOOTH);
}
}
/* note; this is used for fake links in groups too */
void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
{
- bool do_shaded = false;
- bool do_triple = false;
int th_col1 = TH_WIRE_INNER, th_col2 = TH_WIRE_INNER, th_col3 = TH_WIRE;
if (link->fromsock == NULL && link->tosock == NULL)
@@ -3520,8 +3635,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
/* new connection */
if (!link->fromsock || !link->tosock) {
- th_col1 = TH_ACTIVE;
- do_triple = true;
+ th_col1 = th_col2 = TH_ACTIVE;
}
else {
/* going to give issues once... */
@@ -3542,15 +3656,14 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
if (link->tonode && link->tonode->flag & SELECT)
th_col2 = TH_EDGE_SELECT;
}
- do_shaded = true;
- do_triple = true;
}
else {
- th_col1 = TH_REDALERT;
+ th_col1 = th_col2 = TH_REDALERT;
+ // th_col3 = -1; /* no shadow */
}
}
- node_draw_link_bezier(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
+ node_draw_link_bezier(v2d, snode, link, th_col1, th_col2, th_col3);
// node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
}
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 231039b2e22..c82c56ea648 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -359,6 +359,8 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
dy -= NODE_DYS / 2;
/* output sockets */
+ bool add_output_space = false;
+
for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
if (nodeSocketIsHidden(nsock))
continue;
@@ -391,6 +393,12 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
dy = buty;
if (nsock->next)
dy -= NODE_SOCKDY;
+
+ add_output_space = true;
+ }
+
+ if (add_output_space) {
+ dy -= NODE_DY / 4;
}
node->prvr.xmin = locx + NODE_DYS;
@@ -613,13 +621,11 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
bNodeLink *link;
glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
for (link = node->internal_links.first; link; link = link->next)
- node_draw_link_bezier(v2d, snode, link, TH_REDALERT, 0, TH_WIRE, 0, TH_WIRE);
+ node_draw_link_bezier(v2d, snode, link, TH_REDALERT, TH_REDALERT, -1);
glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
}
static void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, PointerRNA node_ptr, bNodeSocket *sock, unsigned pos, unsigned col)
@@ -705,7 +711,7 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv)
node_draw_preview_background(BLI_rctf_size_x(prv) / 10.0f, &draw_rect);
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* premul graphics */
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); /* premul graphics */
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
immDrawPixelsTex(&state, draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect,
@@ -1238,12 +1244,12 @@ void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeT
/* node lines */
glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
+ nodelink_batch_start(snode);
for (link = ntree->links.first; link; link = link->next) {
if (!nodeLinkIsHidden(link))
node_draw_link(&ar->v2d, snode, link);
}
- glDisable(GL_LINE_SMOOTH);
+ nodelink_batch_end(snode);
glDisable(GL_BLEND);
/* draw foreground nodes, last nodes in front */
@@ -1336,7 +1342,7 @@ void drawnodespace(const bContext *C, ARegion *ar)
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
/* only set once */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
/* nodes */
snode_set_context(C);
@@ -1404,7 +1410,6 @@ void drawnodespace(const bContext *C, ARegion *ar)
gpuPushMatrix();
gpuLoadIdentity();
- glaDefine2DArea(&ar->winrct);
wmOrtho2_pixelspace(ar->winx, ar->winy);
WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_2D);
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 7138b63364a..1235133f8ac 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -130,8 +130,11 @@ void NODE_OT_backimage_fit(struct wmOperatorType *ot);
void NODE_OT_backimage_sample(struct wmOperatorType *ot);
/* drawnode.c */
+void nodelink_batch_start(struct SpaceNode *snode);
+void nodelink_batch_end(struct SpaceNode *snode);
+
void node_draw_link(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link);
-void node_draw_link_bezier(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link, int th_col1, bool do_shaded, int th_col2, bool do_triple, int th_col3);
+void node_draw_link_bezier(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link, int th_col1, int th_col2, int th_col3);
bool node_link_bezier_points(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link, float coord_array[][2], int resol);
// void node_draw_link_straight(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3 );
void draw_nodespace_back_pix(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, bNodeInstanceKey parent_key);
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index dc7863bb354..4b4add0e698 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -34,7 +34,7 @@
#include "BLI_utildefines.h"
#include "BLI_rect.h"
-#include "BLI_lasso.h"
+#include "BLI_lasso_2d.h"
#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index c791b9f6eae..241ab60fe43 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -53,7 +53,7 @@
#include "ED_node.h" /* own include */
-#include "ED_util.h"
+#include "ED_undo.h"
/************************* Node Socket Manipulation **************************/
@@ -482,10 +482,10 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
}
NODE_TYPES_END
- qsort(sorted_ntypes, BLI_array_count(sorted_ntypes), sizeof(bNodeType *), ui_node_item_name_compare);
+ qsort(sorted_ntypes, BLI_array_len(sorted_ntypes), sizeof(bNodeType *), ui_node_item_name_compare);
/* generate UI */
- for (int j = 0; j < BLI_array_count(sorted_ntypes); j++) {
+ for (int j = 0; j < BLI_array_len(sorted_ntypes); j++) {
bNodeType *ntype = sorted_ntypes[j];
NodeLinkItem *items;
int totitems;
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 8999555521a..7c3bccd1385 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -37,6 +37,7 @@
#include "DEG_depsgraph_build.h"
#include "DNA_group_types.h"
+#include "DNA_object_types.h"
#include "ED_screen.h"
@@ -91,6 +92,30 @@ static int view_layer_editor_poll(bContext *C)
return (so != NULL) && (so->outlinevis == SO_VIEW_LAYER);
}
+static int outliner_either_collection_editor_poll(bContext *C)
+{
+ SpaceOops *so = CTX_wm_space_outliner(C);
+ return (so != NULL) && (ELEM(so->outlinevis, SO_VIEW_LAYER, SO_COLLECTIONS));
+}
+
+static int outliner_objects_collection_poll(bContext *C)
+{
+ SpaceOops *so = CTX_wm_space_outliner(C);
+ if (so == NULL) {
+ return 0;
+ }
+
+ /* Groups don't support filtering. */
+ if ((so->outlinevis != SO_GROUPS) &&
+ ((so->filter & (SO_FILTER_ENABLE | SO_FILTER_NO_COLLECTION)) ==
+ (SO_FILTER_ENABLE | SO_FILTER_NO_COLLECTION)))
+ {
+ return 0;
+ }
+
+ return ELEM(so->outlinevis, SO_VIEW_LAYER, SO_COLLECTIONS, SO_GROUPS);
+}
+
/* -------------------------------------------------------------------- */
/* collection manager operators */
@@ -317,7 +342,8 @@ static int collection_new_exec(bContext *C, wmOperator *UNUSED(op))
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- SceneCollection *scene_collection = BKE_collection_add(&scene->id, NULL, COLLECTION_TYPE_NONE, NULL);
+ SceneCollection *scene_collection_parent = BKE_collection_master(&scene->id);
+ SceneCollection *scene_collection = BKE_collection_add(&scene->id, scene_collection_parent, COLLECTION_TYPE_NONE, NULL);
BKE_collection_link(view_layer, scene_collection);
DEG_relations_tag_update(bmain);
@@ -468,7 +494,7 @@ static int collection_objects_add_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, struct Object *, ob, selected_objects)
{
- BLI_LISTBASE_FOREACH (LinkData *, link, &data.scene_collections_array) {
+ LISTBASE_FOREACH (LinkData *, link, &data.scene_collections_array) {
SceneCollection *scene_collection = link->data;
BKE_collection_object_add(
&scene->id,
@@ -523,7 +549,7 @@ static int collection_objects_remove_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, struct Object *, ob, selected_objects)
{
- BLI_LISTBASE_FOREACH (LinkData *, link, &data.scene_collections_array) {
+ LISTBASE_FOREACH (LinkData *, link, &data.scene_collections_array) {
SceneCollection *scene_collection = link->data;
BKE_collection_object_remove(
bmain,
@@ -557,6 +583,139 @@ void OUTLINER_OT_collection_objects_remove(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+static TreeElement *outliner_collection_parent_element_get(TreeElement *te)
+{
+ TreeElement *te_parent = te;
+ while ((te_parent = te_parent->parent)) {
+ if (outliner_scene_collection_from_tree_element(te->parent)) {
+ return te_parent;
+ }
+ }
+ return NULL;
+}
+
+static int object_collection_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ Main *bmain = CTX_data_main(C);
+
+ struct ObjectsSelectedData data = {
+ .objects_selected_array = {NULL, NULL},
+ };
+
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data);
+
+ LISTBASE_FOREACH (LinkData *, link, &data.objects_selected_array) {
+ TreeElement *te = (TreeElement *)link->data;
+ Object *ob = (Object *)TREESTORE(te)->id;
+ SceneCollection *scene_collection = NULL;
+
+ TreeElement *te_parent = outliner_collection_parent_element_get(te);
+ if (te_parent != NULL) {
+ scene_collection = outliner_scene_collection_from_tree_element(te_parent);
+ ID *owner_id = TREESTORE(te_parent)->id;
+ BKE_collection_object_remove(bmain, owner_id, scene_collection, ob, true);
+ DEG_id_tag_update(owner_id, DEG_TAG_BASE_FLAGS_UPDATE);
+ }
+ }
+
+ BLI_freelistN(&data.objects_selected_array);
+
+ outliner_cleanup_tree(soops);
+ DEG_relations_tag_update(bmain);
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_object_remove_from_collection(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Object from Collection";
+ ot->idname = "OUTLINER_OT_object_remove_from_collection";
+ ot->description = "Remove selected objects from their respective collection";
+
+ /* api callbacks */
+ ot->exec = object_collection_remove_exec;
+ ot->poll = outliner_objects_collection_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int object_add_to_new_collection_exec(bContext *C, wmOperator *op)
+{
+ int operator_result = OPERATOR_CANCELLED;
+
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ Main *bmain = CTX_data_main(C);
+
+ SceneCollection *scene_collection_parent, *scene_collection_new;
+ TreeElement *te_active, *te_parent;
+
+ struct ObjectsSelectedData data = {{NULL}}, active = {{NULL}};
+
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_HIGHLIGHTED, outliner_find_selected_objects, &active);
+ if (BLI_listbase_is_empty(&active.objects_selected_array)) {
+ BKE_report(op->reports, RPT_ERROR, "No object is selected");
+ goto cleanup;
+ }
+
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data);
+ if (BLI_listbase_is_empty(&data.objects_selected_array)) {
+ BKE_report(op->reports, RPT_ERROR, "No objects are selected");
+ goto cleanup;
+ }
+
+ /* Heuristic to get the "active" / "last object" */
+ te_active = ((LinkData *)active.objects_selected_array.first)->data;
+ te_parent = outliner_collection_parent_element_get(te_active);
+
+ if (te_parent == NULL) {
+ BKE_reportf(op->reports, RPT_ERROR, "Couldn't find collection of \"%s\" object", te_active->name);
+ goto cleanup;
+ }
+
+ ID *owner_id = TREESTORE(te_parent)->id;
+ scene_collection_parent = outliner_scene_collection_from_tree_element(te_parent);
+ scene_collection_new = BKE_collection_add(owner_id, scene_collection_parent, scene_collection_parent->type, NULL);
+
+ LISTBASE_FOREACH (LinkData *, link, &data.objects_selected_array) {
+ TreeElement *te = (TreeElement *)link->data;
+ Object *ob = (Object *)TREESTORE(te)->id;
+ BKE_collection_object_add(owner_id, scene_collection_new, ob);
+ }
+
+ outliner_cleanup_tree(soops);
+ DEG_relations_tag_update(bmain);
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ operator_result = OPERATOR_FINISHED;
+cleanup:
+ BLI_freelistN(&active.objects_selected_array);
+ BLI_freelistN(&data.objects_selected_array);
+ return operator_result;
+}
+
+void OUTLINER_OT_object_add_to_new_collection(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Objects to New Collection";
+ ot->idname = "OUTLINER_OT_object_add_to_new_collection";
+ ot->description = "Add objects to a new collection";
+
+ /* api callbacks */
+ ot->exec = object_add_to_new_collection_exec;
+ ot->poll = outliner_objects_collection_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
struct CollectionDeleteData {
Scene *scene;
SpaceOops *soops;
@@ -757,3 +916,139 @@ void OUTLINER_OT_collection_toggle(wmOperatorType *ot)
#undef ACTION_TOGGLE
#undef ACTION_ENABLE
#undef ACTION_DISABLE
+
+struct CollectionObjectsSelectData {
+ bool error;
+ LayerCollection *layer_collection;
+};
+
+static TreeTraversalAction outliner_find_first_selected_layer_collection(TreeElement *te, void *customdata)
+{
+ struct CollectionObjectsSelectData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ switch (tselem->type) {
+ case TSE_LAYER_COLLECTION:
+ data->layer_collection = te->directdata;
+ return TRAVERSE_BREAK;
+ case TSE_LAYER_COLLECTION_BASE:
+ return TRAVERSE_CONTINUE;
+ default:
+ return TRAVERSE_SKIP_CHILDS;
+ }
+}
+
+static LayerCollection *outliner_active_layer_collection(bContext *C)
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+
+ struct CollectionObjectsSelectData data = {
+ .layer_collection = NULL,
+ };
+
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_first_selected_layer_collection, &data);
+ return data.layer_collection;
+}
+
+static int collection_objects_select_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ LayerCollection *layer_collection = outliner_active_layer_collection(C);
+
+ if (layer_collection == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_layer_collection_objects_select(layer_collection);
+ WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_objects_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Objects";
+ ot->idname = "OUTLINER_OT_collection_objects_select";
+ ot->description = "Select all the collection objects";
+
+ /* api callbacks */
+ ot->exec = collection_objects_select_exec;
+ ot->poll = view_layer_editor_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+struct CollectionDuplicateData {
+ TreeElement *te;
+};
+
+static TreeTraversalAction outliner_find_first_selected_collection(TreeElement *te, void *customdata)
+{
+ struct CollectionDuplicateData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ switch (tselem->type) {
+ case TSE_LAYER_COLLECTION:
+ case TSE_SCENE_COLLECTION:
+ data->te = te;
+ return TRAVERSE_BREAK;
+ case TSE_LAYER_COLLECTION_BASE:
+ default:
+ return TRAVERSE_CONTINUE;
+ }
+}
+
+static TreeElement *outliner_active_collection(bContext *C)
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+
+ struct CollectionDuplicateData data = {
+ .te = NULL,
+ };
+
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_first_selected_collection, &data);
+ return data.te;
+}
+
+static int collection_duplicate_exec(bContext *C, wmOperator *op)
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ TreeElement *te = outliner_active_collection(C);
+
+ BLI_assert(te != NULL);
+ if (BKE_collection_master(TREESTORE(te)->id) == outliner_scene_collection_from_tree_element(te)) {
+ BKE_report(op->reports, RPT_ERROR, "You can't duplicate the master collection");
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (soops->outlinevis) {
+ case SO_COLLECTIONS:
+ BKE_collection_duplicate(TREESTORE(te)->id, (SceneCollection *)te->directdata);
+ break;
+ case SO_VIEW_LAYER:
+ case SO_GROUPS:
+ BKE_layer_collection_duplicate(TREESTORE(te)->id, (LayerCollection *)te->directdata);
+ break;
+ }
+
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, CTX_data_scene(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_duplicate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Duplicate Collection";
+ ot->idname = "OUTLINER_OT_collection_duplicate";
+ ot->description = "Duplicate collection";
+
+ /* api callbacks */
+ ot->exec = collection_duplicate_exec;
+ ot->poll = outliner_either_collection_editor_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 45459bdb030..0f9723dea4b 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -409,7 +409,8 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
case TSE_LAYER_COLLECTION:
{
SceneCollection *sc = outliner_scene_collection_from_tree_element(te);
- BKE_collection_rename(scene, sc, te->name);
+ BKE_collection_rename(tselem->id, sc, te->name);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
break;
}
}
@@ -671,7 +672,7 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOops *soops
}
}
-static void UNUSED_FUNCTION(outliner_draw_rnacols)(ARegion *ar, int sizex)
+static void outliner_draw_rnacols(ARegion *ar, int sizex)
{
View2D *v2d = &ar->v2d;
@@ -697,7 +698,6 @@ static void UNUSED_FUNCTION(outliner_draw_rnacols)(ARegion *ar, int sizex)
immUnbindProgram();
}
-#if 0
static void outliner_draw_rnabuts(uiBlock *block, ARegion *ar, SpaceOops *soops, int sizex, ListBase *lb)
{
TreeElement *te;
@@ -742,7 +742,6 @@ static void outliner_draw_rnabuts(uiBlock *block, ARegion *ar, SpaceOops *soops,
UI_block_emboss_set(block, UI_EMBOSS);
}
-#endif
static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, TreeElement *te)
{
@@ -1241,8 +1240,9 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
#undef ICON_DRAW
}
-static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, ViewLayer *view_layer, SpaceOops *soops,
- ListBase *lb, int level, int xmax, int *offsx, int ys, float alpha_fac)
+static void outliner_draw_iconrow(
+ bContext *C, uiBlock *block, Scene *scene, ViewLayer *view_layer, Object *obedit, SpaceOops *soops,
+ ListBase *lb, int level, int xmax, int *offsx, int ys, float alpha_fac)
{
TreeElement *te;
TreeStoreElem *tselem;
@@ -1263,7 +1263,7 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Vie
if (te->idcode == ID_OB) {
active = (OBACT(view_layer) == (Object *)tselem->id) ? OL_DRAWSEL_NORMAL : OL_DRAWSEL_NONE;
}
- else if (scene->obedit && scene->obedit->data == tselem->id) {
+ else if (obedit && obedit->data == tselem->id) {
active = OL_DRAWSEL_NORMAL;
}
else {
@@ -1303,7 +1303,9 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Vie
/* this tree element always has same amount of branches, so don't draw */
if (tselem->type != TSE_R_LAYER)
- outliner_draw_iconrow(C, block, scene, view_layer, soops, &te->subtree, level + 1, xmax, offsx, ys, alpha_fac);
+ outliner_draw_iconrow(
+ C, block, scene, view_layer, obedit, soops,
+ &te->subtree, level + 1, xmax, offsx, ys, alpha_fac);
}
}
@@ -1327,7 +1329,7 @@ static void outliner_set_coord_tree_element(TreeElement *te, int startx, int sta
static void outliner_draw_tree_element(
- bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ViewLayer *view_layer,
+ bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ViewLayer *view_layer, Object *obedit,
ARegion *ar, SpaceOops *soops, TreeElement *te, bool draw_grayed_out,
int startx, int *starty, TreeElement **te_edit, TreeElement **te_floating)
{
@@ -1391,7 +1393,7 @@ static void outliner_draw_tree_element(
}
}
- else if (scene->obedit && scene->obedit->data == tselem->id) {
+ else if (obedit && obedit->data == tselem->id) {
rgba_float_args_set(color, 1.0f, 1.0f, 1.0f, alpha);
active = OL_DRAWSEL_ACTIVE;
}
@@ -1521,8 +1523,9 @@ static void outliner_draw_tree_element(
immUnbindProgram();
}
- outliner_draw_iconrow(C, block, scene, view_layer, soops, &te->subtree, 0, xmax, &tempx,
- *starty, alpha_fac);
+ outliner_draw_iconrow(
+ C, block, scene, view_layer, obedit, soops, &te->subtree, 0, xmax, &tempx,
+ *starty, alpha_fac);
glDisable(GL_BLEND);
}
@@ -1541,8 +1544,10 @@ static void outliner_draw_tree_element(
/* check if element needs to be drawn grayed out, but also gray out
* childs of a grayed out parent (pass on draw_grayed_out to childs) */
bool draw_childs_grayed_out = draw_grayed_out || (ten->drag_data != NULL);
- outliner_draw_tree_element(C, block, fstyle, scene, view_layer, ar, soops, ten, draw_childs_grayed_out,
- startx + UI_UNIT_X, starty, te_edit, te_floating);
+ outliner_draw_tree_element(
+ C, block, fstyle, scene, view_layer, obedit,
+ ar, soops, ten, draw_childs_grayed_out,
+ startx + UI_UNIT_X, starty, te_edit, te_floating);
}
}
else {
@@ -1781,15 +1786,15 @@ static void outliner_draw_highlights(ARegion *ar, SpaceOops *soops, int startx,
}
static void outliner_draw_tree(
- bContext *C, uiBlock *block, Scene *scene, ViewLayer *view_layer, ARegion *ar,
- SpaceOops *soops, const bool has_restrict_icons,
+ bContext *C, uiBlock *block, Scene *scene, ViewLayer *view_layer, Object *obedit,
+ ARegion *ar, SpaceOops *soops, const bool has_restrict_icons,
TreeElement **te_edit)
{
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
TreeElement *te_floating = NULL;
int starty, startx;
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // only once
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // only once
if (soops->outlinevis == SO_DATABLOCKS) {
/* struct marks */
@@ -1822,8 +1827,10 @@ static void outliner_draw_tree(
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
startx = 0;
for (TreeElement *te = soops->tree.first; te; te = te->next) {
- outliner_draw_tree_element(C, block, fstyle, scene, view_layer, ar, soops, te, te->drag_data != NULL,
- startx, &starty, te_edit, &te_floating);
+ outliner_draw_tree_element(
+ C, block, fstyle, scene, view_layer, obedit,
+ ar, soops, te, te->drag_data != NULL,
+ startx, &starty, te_edit, &te_floating);
}
if (te_floating && te_floating->drag_data->insert_handle) {
outliner_draw_tree_element_floating(ar, te_floating);
@@ -1898,9 +1905,12 @@ static void outliner_draw_restrictcols(ARegion *ar)
void draw_outliner(const bContext *C)
{
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
Main *mainvar = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -1960,9 +1970,16 @@ void draw_outliner(const bContext *C)
/* draw outliner stuff (background, hierarchy lines and names) */
outliner_back(ar);
block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
- outliner_draw_tree((bContext *)C, block, scene, view_layer, ar, soops, has_restrict_icons, &te_edit);
+ outliner_draw_tree(
+ (bContext *)C, block, scene, view_layer, obedit,
+ ar, soops, has_restrict_icons, &te_edit);
- if ((soops->outlinevis == SO_ID_ORPHANS) && has_restrict_icons) {
+ if (soops->outlinevis == SO_DATABLOCKS) {
+ /* draw rna buttons */
+ outliner_draw_rnacols(ar, sizex_rna);
+ outliner_draw_rnabuts(block, ar, soops, sizex_rna, &soops->tree);
+ }
+ else if ((soops->outlinevis == SO_ID_ORPHANS) && has_restrict_icons) {
/* draw user toggle columns */
outliner_draw_restrictcols(ar);
outliner_draw_userbuts(block, ar, soops, &soops->tree);
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index fc0e30c78ce..f5d117922c0 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -51,7 +51,6 @@
#include "BKE_animsys.h"
#include "BKE_context.h"
-#include "BKE_global.h"
#include "BKE_idcode.h"
#include "BKE_layer.h"
#include "BKE_library.h"
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 30ede0a5e55..13567c2a5a2 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -37,6 +37,7 @@
/* internal exports only */
struct ARegion;
+struct ListBase;
struct wmOperatorType;
struct TreeElement;
struct TreeStoreElem;
@@ -50,7 +51,7 @@ struct bPoseChannel;
struct EditBone;
struct wmEvent;
struct wmKeyConfig;
-
+struct EvaluationContext;
typedef enum TreeElementInsertType {
TE_INSERT_BEFORE,
@@ -191,8 +192,16 @@ void outliner_cleanup_tree(struct SpaceOops *soops);
void outliner_free_tree_element(TreeElement *element, ListBase *parent_subtree);
void outliner_remove_treestore_element(struct SpaceOops *soops, TreeStoreElem *tselem);
-void outliner_build_tree(struct Main *mainvar, struct Scene *scene, struct ViewLayer *view_layer,
- struct SpaceOops *soops, struct ARegion *ar);
+void outliner_build_tree(
+ struct Main *mainvar,
+ struct Scene *scene, struct ViewLayer *view_layer,
+ struct SpaceOops *soops, struct ARegion *ar);
+
+typedef struct ObjectsSelectedData {
+ struct ListBase objects_selected_array;
+} ObjectsSelectedData;
+
+TreeTraversalAction outliner_find_selected_objects(struct TreeElement *te, void *customdata);
/* outliner_draw.c ---------------------------------------------- */
@@ -344,7 +353,11 @@ void OUTLINER_OT_collection_toggle(struct wmOperatorType *ot);
void OUTLINER_OT_collection_link(struct wmOperatorType *ot);
void OUTLINER_OT_collection_unlink(struct wmOperatorType *ot);
void OUTLINER_OT_collection_new(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_duplicate(struct wmOperatorType *ot);
void OUTLINER_OT_collection_objects_remove(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot);
+void OUTLINER_OT_object_add_to_new_collection(struct wmOperatorType *ot);
+void OUTLINER_OT_object_remove_from_collection(struct wmOperatorType *ot);
void OUTLINER_OT_collection_objects_add(struct wmOperatorType *ot);
void OUTLINER_OT_collection_nested_new(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 52f27b9708e..ba501ac7db5 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -474,11 +474,15 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_collection_link);
WM_operatortype_append(OUTLINER_OT_collection_unlink);
WM_operatortype_append(OUTLINER_OT_collection_new);
+ WM_operatortype_append(OUTLINER_OT_collection_duplicate);
WM_operatortype_append(OUTLINER_OT_collection_nested_new);
WM_operatortype_append(OUTLINER_OT_collection_delete_selected);
WM_operatortype_append(OUTLINER_OT_collection_objects_add);
WM_operatortype_append(OUTLINER_OT_collection_objects_remove);
+ WM_operatortype_append(OUTLINER_OT_collection_objects_select);
+ WM_operatortype_append(OUTLINER_OT_object_add_to_new_collection);
+ WM_operatortype_append(OUTLINER_OT_object_remove_from_collection);
}
static wmKeyMap *outliner_item_drag_drop_modal_keymap(wmKeyConfig *keyconf)
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index b9222e62bb0..2f44420f3b7 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -57,7 +57,7 @@
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_sequencer.h"
-#include "ED_util.h"
+#include "ED_undo.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -194,8 +194,8 @@ static eOLDrawState tree_element_set_active_object(
}
}
- if (ob != scene->obedit)
- ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
+ if (ob != OBEDIT_FROM_VIEW_LAYER(view_layer))
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR | EM_DO_UNDO);
return OL_DRAWSEL_NORMAL;
}
@@ -547,7 +547,7 @@ static eOLDrawState tree_element_active_bone(
/* ebones only draw in editmode armature */
-static void tree_element_active_ebone__sel(bContext *C, Scene *scene, bArmature *arm, EditBone *ebone, short sel)
+static void tree_element_active_ebone__sel(bContext *C, Object *obedit, bArmature *arm, EditBone *ebone, short sel)
{
if (sel) {
ebone->flag |= BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL;
@@ -561,34 +561,34 @@ static void tree_element_active_ebone__sel(bContext *C, Scene *scene, bArmature
if (ebone->parent && (ebone->flag & BONE_CONNECTED)) ebone->parent->flag &= ~BONE_TIPSEL;
}
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, scene->obedit);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, obedit);
}
static eOLDrawState tree_element_active_ebone(
- bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set, bool recursive)
+ bContext *C, TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set, bool recursive)
{
- BLI_assert(scene->obedit != NULL);
-
- bArmature *arm = scene->obedit->data;
+ Object *obedit = CTX_data_edit_object(C);
+ BLI_assert(obedit != NULL);
+ bArmature *arm = obedit->data;
EditBone *ebone = te->directdata;
eOLDrawState status = OL_DRAWSEL_NONE;
if (set != OL_SETSEL_NONE) {
if (set == OL_SETSEL_NORMAL) {
if (!(ebone->flag & BONE_HIDDEN_A)) {
- ED_armature_deselect_all(scene->obedit);
- tree_element_active_ebone__sel(C, scene, arm, ebone, true);
+ ED_armature_deselect_all(obedit);
+ tree_element_active_ebone__sel(C, obedit, arm, ebone, true);
status = OL_DRAWSEL_NORMAL;
}
}
else if (set == OL_SETSEL_EXTEND) {
if (!(ebone->flag & BONE_HIDDEN_A)) {
if (!(ebone->flag & BONE_SELECTED)) {
- tree_element_active_ebone__sel(C, scene, arm, ebone, true);
+ tree_element_active_ebone__sel(C, obedit, arm, ebone, true);
status = OL_DRAWSEL_NORMAL;
}
else {
/* entirely selected, so de-select */
- tree_element_active_ebone__sel(C, scene, arm, ebone, false);
+ tree_element_active_ebone__sel(C, obedit, arm, ebone, false);
status = OL_DRAWSEL_NONE;
}
}
@@ -656,7 +656,7 @@ static eOLDrawState tree_element_active_text(
}
static eOLDrawState tree_element_active_pose(
- bContext *C, Scene *scene, ViewLayer *view_layer, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
+ bContext *C, ViewLayer *view_layer, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
{
Object *ob = (Object *)tselem->id;
Base *base = BKE_view_layer_base_find(view_layer, ob);
@@ -667,13 +667,16 @@ static eOLDrawState tree_element_active_pose(
}
if (set != OL_SETSEL_NONE) {
- if (scene->obedit)
- ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
+ if (OBEDIT_FROM_VIEW_LAYER(view_layer)) {
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR | EM_DO_UNDO);
+ }
- if (ob->mode & OB_MODE_POSE)
- ED_armature_exit_posemode(C, base);
- else
- ED_armature_enter_posemode(C, base);
+ if (ob->mode & OB_MODE_POSE) {
+ ED_object_posemode_exit(C, ob);
+ }
+ else {
+ ED_object_posemode_enter(C, ob);
+ }
}
else {
if (ob->mode & OB_MODE_POSE) {
@@ -847,7 +850,7 @@ eOLDrawState tree_element_type_active(
case TSE_BONE:
return tree_element_active_bone(C, view_layer, te, tselem, set, recursive);
case TSE_EBONE:
- return tree_element_active_ebone(C, scene, te, tselem, set, recursive);
+ return tree_element_active_ebone(C, te, tselem, set, recursive);
case TSE_MODIFIER:
return tree_element_active_modifier(C, scene, view_layer, te, tselem, set);
case TSE_LINKED_OB:
@@ -861,7 +864,7 @@ eOLDrawState tree_element_type_active(
case TSE_LINKED_PSYS:
return tree_element_active_psys(C, scene, te, tselem, set);
case TSE_POSE_BASE:
- return tree_element_active_pose(C, scene, view_layer, te, tselem, set);
+ return tree_element_active_pose(C, view_layer, te, tselem, set);
case TSE_POSE_CHANNEL:
return tree_element_active_posechannel(C, scene, view_layer, te, tselem, set, recursive);
case TSE_CONSTRAINT:
@@ -921,7 +924,7 @@ static void do_outliner_item_activate_tree_element(
if (extend) {
int sel = BA_SELECT;
- FOREACH_GROUP_BASE(gr, base)
+ FOREACH_GROUP_BASE_BEGIN(gr, base)
{
if (base->flag & BASE_SELECTED) {
sel = BA_DESELECT;
@@ -930,16 +933,16 @@ static void do_outliner_item_activate_tree_element(
}
FOREACH_GROUP_BASE_END
- FOREACH_GROUP_OBJECT(gr, object)
+ FOREACH_GROUP_OBJECT_BEGIN(gr, object)
{
ED_object_base_select(BKE_view_layer_base_find(view_layer, object), sel);
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
else {
BKE_view_layer_base_deselect_all(view_layer);
- FOREACH_GROUP_OBJECT(gr, object)
+ FOREACH_GROUP_OBJECT_BEGIN(gr, object)
{
Base *base = BKE_view_layer_base_find(view_layer, object);
/* Object may not be in this scene */
@@ -949,7 +952,7 @@ static void do_outliner_item_activate_tree_element(
}
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index eaa3267e99d..735e2b5a37a 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -73,7 +73,7 @@
#include "ED_scene.h"
#include "ED_screen.h"
#include "ED_sequencer.h"
-#include "ED_util.h"
+#include "ED_undo.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -419,9 +419,9 @@ static void object_delete_cb(
}
// check also library later
- if (scene->obedit == ob)
- ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
-
+ if (ob == CTX_data_edit_object(C)) {
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR | EM_DO_UNDO);
+ }
ED_object_base_free_and_unlink(CTX_data_main(C), scene, ob);
/* leave for ED_outliner_id_unref to handle */
#if 0
@@ -541,7 +541,7 @@ static void group_linkobs2scene_cb(
Group *group = (Group *)tselem->id;
Base *base;
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
base = BKE_view_layer_base_find(view_layer, object);
if (!base) {
@@ -553,7 +553,7 @@ static void group_linkobs2scene_cb(
base->flag |= BASE_SELECTED;
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
static void group_instance_cb(
@@ -675,7 +675,9 @@ typedef enum eOutliner_PropModifierOps {
typedef enum eOutliner_PropCollectionOps {
OL_COLLECTION_OP_OBJECTS_ADD = 1,
OL_COLLECTION_OP_OBJECTS_REMOVE,
+ OL_COLLECTION_OP_OBJECTS_SELECT,
OL_COLLECTION_OP_COLLECTION_NEW,
+ OL_COLLECTION_OP_COLLECTION_COPY,
OL_COLLECTION_OP_COLLECTION_DEL,
OL_COLLECTION_OP_COLLECTION_UNLINK,
OL_COLLECTION_OP_GROUP_CREATE,
@@ -860,6 +862,10 @@ static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tsel
WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
te->store_elem->flag &= ~TSE_SELECTED;
}
+ else if (event == OL_COLLECTION_OP_OBJECTS_SELECT) {
+ BKE_layer_collection_objects_select(lc);
+ WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
+ }
else if (event == OL_COLLECTION_OP_COLLECTION_NEW) {
if (GS(id->name) == ID_GR) {
BKE_collection_add(id, sc, COLLECTION_TYPE_GROUP_INTERNAL, NULL);
@@ -870,6 +876,11 @@ static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tsel
}
WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
}
+ else if (event == OL_COLLECTION_OP_COLLECTION_COPY) {
+ BKE_layer_collection_duplicate(id, lc);
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ }
else if (event == OL_COLLECTION_OP_COLLECTION_UNLINK) {
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -969,7 +980,7 @@ static void object_delete_hierarchy_cb(
{
ViewLayer *view_layer = CTX_data_view_layer(C);
Base *base = (Base *)te->directdata;
- Object *obedit = scene->obedit;
+ Object *obedit = CTX_data_edit_object(C);
if (!base) {
base = BKE_view_layer_base_find(view_layer, (Object *)tselem->id);
@@ -978,7 +989,7 @@ static void object_delete_hierarchy_cb(
/* Check also library later. */
for (; obedit && (obedit != base->object); obedit = obedit->parent);
if (obedit == base->object) {
- ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR | EM_DO_UNDO);
}
outline_delete_hierarchy(C, reports, scene, base);
@@ -1016,9 +1027,6 @@ static const EnumPropertyItem prop_object_op_types[] = {
{OL_OP_DELETE_HIERARCHY, "DELETE_HIERARCHY", 0, "Delete Hierarchy", ""},
{OL_OP_REMAP, "REMAP", 0, "Remap Users",
"Make all users of selected data-blocks to use instead a new chosen one"},
- {OL_OP_TOGVIS, "TOGVIS", 0, "Toggle Visible", ""},
- {OL_OP_TOGSEL, "TOGSEL", 0, "Toggle Selectable", ""},
- {OL_OP_TOGREN, "TOGREN", 0, "Toggle Renderable", ""},
{OL_OP_RENAME, "RENAME", 0, "Rename", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -1844,39 +1852,18 @@ void OUTLINER_OT_modifier_operation(wmOperatorType *ot)
/* ******************** */
-static EnumPropertyItem prop_collection_op_none_types[] = {
+static EnumPropertyItem prop_collection_op_types[] = {
{OL_COLLECTION_OP_OBJECTS_ADD, "OBJECTS_ADD", ICON_ZOOMIN, "Add Selected", "Add selected objects to collection"},
{OL_COLLECTION_OP_OBJECTS_REMOVE, "OBJECTS_REMOVE", ICON_X, "Remove Selected", "Remove selected objects from collection"},
+ {OL_COLLECTION_OP_OBJECTS_SELECT, "OBJECTS_SELECT", ICON_RESTRICT_SELECT_OFF, "Select Objects", "Select collection objects"},
{OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"},
+ {OL_COLLECTION_OP_COLLECTION_COPY, "COLLECTION_DUPLI", ICON_NONE, "Duplicate Collection", "Duplicate the collection"},
{OL_COLLECTION_OP_COLLECTION_UNLINK, "COLLECTION_UNLINK", ICON_UNLINKED, "Unlink", "Unlink collection"},
{OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_DEL", ICON_X, "Delete Collection", "Delete the collection"},
{OL_COLLECTION_OP_GROUP_CREATE, "GROUP_CREATE", ICON_GROUP, "Create Group", "Turn the collection into a group collection"},
{0, NULL, 0, NULL, NULL}
};
-static EnumPropertyItem prop_collection_op_group_internal_types[] = {
- {OL_COLLECTION_OP_OBJECTS_ADD, "OBJECTS_ADD", ICON_ZOOMIN, "Add Selected", "Add selected objects to collection"},
- {OL_COLLECTION_OP_OBJECTS_REMOVE, "OBJECTS_REMOVE", ICON_X, "Remove Selected", "Remove selected objects from collection"},
- {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"},
- {OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_DEL", ICON_X, "Delete Collection", "Delete the collection"},
- {0, NULL, 0, NULL, NULL}
-};
-
-static const EnumPropertyItem *outliner_collection_operation_type_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
-{
- *r_free = false;
- SpaceOops *soops = CTX_wm_space_outliner(C);
-
- switch (soops->outlinevis) {
- case SO_GROUPS:
- return prop_collection_op_group_internal_types;
- case SO_VIEW_LAYER:
- return prop_collection_op_none_types;
- }
- return NULL;
-}
-
static int outliner_collection_operation_exec(bContext *C, wmOperator *op)
{
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -1895,6 +1882,31 @@ static int outliner_collection_operation_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static int outliner_collection_operation_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ wmOperatorType *ot = op->type;
+ EnumPropertyItem *prop = &prop_collection_op_types[0];
+
+ uiPopupMenu *pup = UI_popup_menu_begin(C, "Collection", ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+
+ for (int i = 0; i < (ARRAY_SIZE(prop_collection_op_types) - 1); i++, prop++) {
+ if (soops->outlinevis != SO_GROUPS ||
+ !ELEM(prop->value,
+ OL_COLLECTION_OP_OBJECTS_SELECT,
+ OL_COLLECTION_OP_COLLECTION_UNLINK,
+ OL_COLLECTION_OP_GROUP_CREATE))
+ {
+ uiItemEnumO_ptr(layout, ot, NULL, prop->icon, "type", prop->value);
+ }
+ }
+
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
+}
+
void OUTLINER_OT_collection_operation(wmOperatorType *ot)
{
PropertyRNA *prop;
@@ -1905,14 +1917,13 @@ void OUTLINER_OT_collection_operation(wmOperatorType *ot)
ot->description = "";
/* callbacks */
- ot->invoke = WM_menu_invoke;
+ ot->invoke = outliner_collection_operation_invoke;
ot->exec = outliner_collection_operation_exec;
ot->poll = ED_operator_outliner_active;
ot->flag = 0;
- prop = RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Collection Operation", "");
- RNA_def_enum_funcs(prop, outliner_collection_operation_type_itemf);
+ prop = RNA_def_enum(ot->srna, "type", prop_collection_op_types, OL_COLLECTION_OP_OBJECTS_ADD, "Collection Operation", "");
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}
@@ -2051,7 +2062,7 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
}
}
else if (objectlevel) {
- WM_operator_name_call(C, "OUTLINER_OT_object_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+ WM_menu_name_call(C, "OUTLINER_MT_context_object", WM_OP_INVOKE_REGION_WIN);
}
else if (idlevel) {
if (idlevel == -1 || datalevel) {
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 205f70e58dc..9f44b5bfc02 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -130,7 +130,7 @@ static void outliner_storage_cleanup(SpaceOops *soops)
}
if (unused) {
- if (BLI_mempool_count(ts) == unused) {
+ if (BLI_mempool_len(ts) == unused) {
BLI_mempool_destroy(ts);
soops->treestore = NULL;
if (soops->treehash) {
@@ -140,7 +140,7 @@ static void outliner_storage_cleanup(SpaceOops *soops)
}
else {
TreeStoreElem *tsenew;
- BLI_mempool *new_ts = BLI_mempool_create(sizeof(TreeStoreElem), BLI_mempool_count(ts) - unused,
+ BLI_mempool *new_ts = BLI_mempool_create(sizeof(TreeStoreElem), BLI_mempool_len(ts) - unused,
512, BLI_MEMPOOL_ALLOW_ITER);
BLI_mempool_iternew(ts, &iter);
while ((tselem = BLI_mempool_iterstep(&iter))) {
@@ -416,11 +416,7 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s
#endif
}
-struct ObjectsSelectedData {
- ListBase objects_selected_array;
-};
-
-static TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *customdata)
+TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *customdata)
{
struct ObjectsSelectedData *data = customdata;
TreeStoreElem *tselem = TREESTORE(te);
@@ -466,7 +462,7 @@ static void outliner_object_reorder(
TREESTORE(insert_element)->flag |= TSE_SELECTED;
outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data);
- BLI_LISTBASE_FOREACH (LinkData *, link, &data.objects_selected_array) {
+ LISTBASE_FOREACH (LinkData *, link, &data.objects_selected_array) {
TreeElement *ten_selected = (TreeElement *)link->data;
Object *ob = (Object *)TREESTORE(ten_selected)->id;
@@ -2183,7 +2179,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
{
TreeElement *te = NULL, *ten;
TreeStoreElem *tselem;
- int show_opened = !soops->treestore || !BLI_mempool_count(soops->treestore); /* on first view, we open scenes */
+ int show_opened = !soops->treestore || !BLI_mempool_len(soops->treestore); /* on first view, we open scenes */
/* Are we looking for something - we want to tag parents to filter child matches
* - NOT in datablocks view - searching all datablocks takes way too long to be useful
@@ -2330,11 +2326,11 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
}
else if (soops->outlinevis == SO_COLLECTIONS) {
if ((soops->filter & SO_FILTER_ENABLE) && (soops->filter & SO_FILTER_NO_COLLECTION)) {
- FOREACH_SCENE_OBJECT(scene, ob)
+ FOREACH_SCENE_OBJECT_BEGIN(scene, ob)
{
outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0);
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
outliner_make_hierarchy(&soops->tree);
}
else {
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 04dbab0b853..8e5863fd514 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -58,7 +58,6 @@
#include "BIF_glutil.h"
-#include "GPU_compositing.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
@@ -330,7 +329,7 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
}
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
for (seq = seqbase->first; seq; seq = seq->next) {
chan_min = min_ii(chan_min, seq->machine);
@@ -435,7 +434,7 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
{
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
if (seq->flag & whichsel) {
immUniformColor4ub(0, 0, 0, 80);
@@ -620,7 +619,7 @@ static void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq, u
if (seq->startofs || seq->endofs) {
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
color3ubv_from_seq(scene, seq, col);
@@ -664,7 +663,7 @@ static void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq, u
if (seq->startstill || seq->endstill) {
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
color3ubv_from_seq(scene, seq, col);
UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.5f, 60);
@@ -730,7 +729,7 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
background_col[3] = 128;
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
else {
background_col[3] = 255;
@@ -842,7 +841,7 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
col[3] = 96;
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
immUniformColor4ubv(col);
}
@@ -924,12 +923,6 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int
rectx, recty, proxy_size,
&context);
context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
- if (scene->r.seq_flag & R_SEQ_CAMERA_DOF) {
- if (sseq->compositor == NULL) {
- sseq->compositor = GPU_fx_compositor_create();
- }
- context.gpu_fx = sseq->compositor;
- }
/* sequencer could start rendering, in this case we need to be sure it wouldn't be canceled
* by Esc pressed somewhere in the past
@@ -1226,7 +1219,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
/* Format needs to be created prior to any immBindProgram call.
@@ -1316,6 +1309,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
glGenTextures(1, (GLuint *)&texid);
+ glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -1329,7 +1323,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
if (!glsl_used) {
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
immUniformColor3f(1.0f, 1.0f, 1.0f);
- immUniform1i("image", GL_TEXTURE0);
+ immUniform1i("image", 0);
}
immBegin(GWN_PRIM_TRI_FAN, 4);
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index cb0c5bd3717..9a0578fe220 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -671,6 +671,9 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
Sequence *seqn = NULL;
bool skip_dup = false;
+ /* Unlike soft-cut, it's important to use the same value for both strips. */
+ const bool is_end_exact = ((seq->start + seq->len) == cutframe);
+
/* backup values */
ts.start = seq->start;
ts.machine = seq->machine;
@@ -683,7 +686,7 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
ts.anim_startofs = seq->anim_startofs;
ts.anim_endofs = seq->anim_endofs;
ts.len = seq->len;
-
+
/* First Strip! */
/* strips with extended stillfames before */
@@ -695,6 +698,8 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
BKE_sequence_calc(scene, seq);
}
+ /* Important to offset the start when 'cutframe == seq->start'
+ * because we need at least one frame of content after start/end still have clipped it. */
if ((seq->startstill) && (cutframe <= seq->start)) {
/* don't do funny things with METAs ... */
if (seq->type == SEQ_TYPE_META) {
@@ -709,13 +714,15 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
}
}
/* normal strip */
- else if ((cutframe >= seq->start) && (cutframe < (seq->start + seq->len))) {
+ else if ((is_end_exact == false) &&
+ ((cutframe >= seq->start) && (cutframe <= (seq->start + seq->len))))
+ {
seq->endofs = 0;
seq->endstill = 0;
seq->anim_endofs += (seq->start + seq->len) - cutframe;
}
/* strips with extended stillframes after */
- else if (((seq->start + seq->len) == cutframe) ||
+ else if ((is_end_exact == true) ||
(((seq->start + seq->len) < cutframe) && (seq->endstill)))
{
seq->endstill -= seq->enddisp - cutframe;
@@ -735,7 +742,11 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
if (seqn) {
seqn->flag |= SELECT;
-
+
+ /* Important not to re-assign this (unlike soft-cut) */
+#if 0
+ is_end_exact = ((seqn->start + seqn->len) == cutframe);
+#endif
/* Second Strip! */
/* strips with extended stillframes before */
if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
@@ -744,9 +755,11 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
seqn->anim_endofs = ts.anim_endofs;
seqn->endstill = ts.endstill;
}
-
+
/* normal strip */
- else if ((cutframe >= seqn->start) && (cutframe < (seqn->start + seqn->len))) {
+ else if ((is_end_exact == false) &&
+ ((cutframe >= seqn->start) && (cutframe <= (seqn->start + seqn->len))))
+ {
seqn->start = cutframe;
seqn->startstill = 0;
seqn->startofs = 0;
@@ -755,9 +768,9 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
seqn->anim_endofs = ts.anim_endofs;
seqn->endstill = ts.endstill;
}
-
+
/* strips with extended stillframes after */
- else if (((seqn->start + seqn->len) == cutframe) ||
+ else if ((is_end_exact == true) ||
(((seqn->start + seqn->len) < cutframe) && (seqn->endstill)))
{
seqn->start = cutframe;
@@ -766,7 +779,7 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
seqn->endstill = ts.enddisp - cutframe - 1;
seqn->startstill = 0;
}
-
+
BKE_sequence_reload_new_file(scene, seqn, false);
BKE_sequence_calc(scene, seqn);
}
@@ -779,6 +792,8 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
Sequence *seqn = NULL;
bool skip_dup = false;
+ bool is_end_exact = ((seq->start + seq->len) == cutframe);
+
/* backup values */
ts.start = seq->start;
ts.machine = seq->machine;
@@ -791,10 +806,12 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
ts.anim_startofs = seq->anim_startofs;
ts.anim_endofs = seq->anim_endofs;
ts.len = seq->len;
-
+
/* First Strip! */
/* strips with extended stillfames before */
-
+
+ /* Important to offset the start when 'cutframe == seq->start'
+ * because we need at least one frame of content after start/end still have clipped it. */
if ((seq->startstill) && (cutframe <= seq->start)) {
/* don't do funny things with METAs ... */
if (seq->type == SEQ_TYPE_META) {
@@ -809,11 +826,13 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
}
}
/* normal strip */
- else if ((cutframe >= seq->start) && (cutframe < (seq->start + seq->len))) {
+ else if ((is_end_exact == false) &&
+ (cutframe >= seq->start) && (cutframe <= (seq->start + seq->len)))
+ {
seq->endofs = (seq->start + seq->len) - cutframe;
}
/* strips with extended stillframes after */
- else if (((seq->start + seq->len) == cutframe) ||
+ else if ((is_end_exact == true) ||
(((seq->start + seq->len) < cutframe) && (seq->endstill)))
{
seq->endstill -= seq->enddisp - cutframe;
@@ -832,7 +851,9 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
if (seqn) {
seqn->flag |= SELECT;
-
+
+ is_end_exact = ((seqn->start + seqn->len) == cutframe);
+
/* Second Strip! */
/* strips with extended stillframes before */
if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
@@ -843,15 +864,17 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
}
/* normal strip */
- if ((cutframe >= seqn->start) && (cutframe < (seqn->start + seqn->len))) {
+ else if ((is_end_exact == false) &&
+ (cutframe >= seqn->start) && (cutframe <= (seqn->start + seqn->len)))
+ {
seqn->startstill = 0;
seqn->startofs = cutframe - ts.start;
seqn->endofs = ts.endofs;
seqn->endstill = ts.endstill;
}
-
+
/* strips with extended stillframes after */
- else if (((seqn->start + seqn->len) == cutframe) ||
+ else if ((is_end_exact == true) ||
(((seqn->start + seqn->len) < cutframe) && (seqn->endstill)))
{
seqn->start = cutframe - ts.len + 1;
@@ -859,7 +882,7 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
seqn->endstill = ts.enddisp - cutframe - 1;
seqn->startstill = 0;
}
-
+
BKE_sequence_calc(scene, seqn);
}
return seqn;
@@ -2785,7 +2808,7 @@ static int sequencer_view_zoom_ratio_exec(bContext *C, wmOperator *op)
float facx = BLI_rcti_size_x(&v2d->mask) / winx;
float facy = BLI_rcti_size_y(&v2d->mask) / winy;
- BLI_rctf_resize(&v2d->cur, floorf(winx * facx / ratio + 0.5f), floorf(winy * facy / ratio + 0.5f));
+ BLI_rctf_resize(&v2d->cur, ceilf(winx * facx / ratio + 0.5f), ceilf(winy * facy / ratio + 0.5f));
ED_region_tag_redraw(CTX_wm_region(C));
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 23387f291e6..da16ac5acaa 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -60,8 +60,6 @@
#include "IMB_imbuf.h"
-#include "GPU_compositing.h"
-
#include "sequencer_intern.h" // own include
/**************************** common state *****************************/
@@ -220,11 +218,6 @@ static void sequencer_free(SpaceLink *sl)
if (scopes->histogram_ibuf)
IMB_freeImBuf(scopes->histogram_ibuf);
-
- if (sseq->compositor != NULL) {
- GPU_fx_compositor_destroy(sseq->compositor);
- sseq->compositor = NULL;
- }
}
diff --git a/source/blender/editors/space_text/CMakeLists.txt b/source/blender/editors/space_text/CMakeLists.txt
index 39b48f5b52c..91420a5d63a 100644
--- a/source/blender/editors/space_text/CMakeLists.txt
+++ b/source/blender/editors/space_text/CMakeLists.txt
@@ -48,6 +48,7 @@ set(SRC
text_format_py.c
text_header.c
text_ops.c
+ text_undo.c
text_format.h
text_intern.h
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index da5fa9da046..9163831c333 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -241,7 +241,7 @@ static void get_suggest_prefix(Text *text, int offset)
texttool_suggest_prefix(line + i, len);
}
-static void confirm_suggestion(Text *text)
+static void confirm_suggestion(Text *text, TextUndoBuf *utxt)
{
SuggItem *sel;
int i, over = 0;
@@ -260,7 +260,7 @@ static void confirm_suggestion(Text *text)
// for (i = 0; i < skipleft; i++)
// txt_move_left(text, 0);
BLI_assert(memcmp(sel->name, &line[i], over) == 0);
- txt_insert_buf(text, sel->name + over);
+ txt_insert_buf(text, utxt, sel->name + over);
// for (i = 0; i < skipleft; i++)
// txt_move_right(text, 0);
@@ -284,7 +284,8 @@ static int text_autocomplete_invoke(bContext *C, wmOperator *op, const wmEvent *
ED_area_tag_redraw(CTX_wm_area(C));
if (texttool_suggest_first() == texttool_suggest_last()) {
- confirm_suggestion(st->text);
+ TextUndoBuf *utxt = NULL; // FIXME
+ confirm_suggestion(st->text, utxt);
text_update_line_edited(st->text->curl);
text_autocomplete_free(C, op);
return OPERATOR_FINISHED;
@@ -314,6 +315,8 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
(void)text;
+ TextUndoBuf *utxt = NULL; // FIXME
+
if (st->doplugins && texttool_text_is_active(st->text)) {
if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST;
if (texttool_docs_get()) tools |= TOOL_DOCUMENT;
@@ -340,7 +343,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
case MIDDLEMOUSE:
if (event->val == KM_PRESS) {
if (text_do_suggest_select(st, ar)) {
- confirm_suggestion(st->text);
+ confirm_suggestion(st->text, utxt);
text_update_line_edited(st->text->curl);
swallow = 1;
}
@@ -375,7 +378,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
case PADENTER:
if (event->val == KM_PRESS) {
if (tools & TOOL_SUGG_LIST) {
- confirm_suggestion(st->text);
+ confirm_suggestion(st->text, utxt);
text_update_line_edited(st->text->curl);
swallow = 1;
draw = 1;
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 62fde49cade..3949aa928c9 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -1207,7 +1207,7 @@ static void draw_text_decoration(SpaceText *st, ARegion *ar)
immUniformColor4ub(255, 255, 255, 32);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
immRecti(pos, x1 - 4, y1, x2, y2);
glDisable(GL_BLEND);
diff --git a/source/blender/editors/space_text/text_format_pov.c b/source/blender/editors/space_text/text_format_pov.c
index 1ef3322711c..4c9abecedd6 100644
--- a/source/blender/editors/space_text/text_format_pov.c
+++ b/source/blender/editors/space_text/text_format_pov.c
@@ -486,7 +486,7 @@ static int txtfmt_pov_find_specialvar(const char *string)
{
int i, len;
/* Modifiers */
- if (STR_LITERAL_STARTSWITH(string, "dispersion_samples", len)) i = len;
+ if (STR_LITERAL_STARTSWITH(string, "dispersion_samples", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "projected_through", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "double_illuminate", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "expand_thresholds", len)) i = len;
@@ -498,7 +498,7 @@ static int txtfmt_pov_find_specialvar(const char *string)
else if (STR_LITERAL_STARTSWITH(string, "max_trace_level", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "gray_threshold", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "pretrace_start", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "normal_indices", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "normal_indices", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "normal_vectors", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "vertex_vectors", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "noise_generator", len)) i = len;
@@ -577,7 +577,7 @@ static int txtfmt_pov_find_specialvar(const char *string)
else if (STR_LITERAL_STARTSWITH(string, "autostop", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "caustics", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "octaves", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "aa_level", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "aa_level", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "frequency", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "fog_offset", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "modulation", len)) i = len;
@@ -642,45 +642,45 @@ static int txtfmt_pov_find_specialvar(const char *string)
else if (STR_LITERAL_STARTSWITH(string, "radius", len)) i = len;
/* Camera Types and options*/
else if (STR_LITERAL_STARTSWITH(string, "omni_directional_stereo", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "lambert_cylindrical", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "miller_cylindrical", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "lambert_azimuthal", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ultra_wide_angle", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "camera_direction", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "camera_location ", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "van_der_grinten", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "aitoff_hammer", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "smyth_craster", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "orthographic", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "camera_right", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "blur_samples", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "plate_carree", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "camera_type", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "perspective", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "mesh_camera", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "focal_point", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "balthasart", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "confidence", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "parallaxe", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "hobo_dyer", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "camera_up", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "panoramic", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "eckert_vi", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "eckert_iv", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "mollweide", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "aperture", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "behrmann", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "variance", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "stereo", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "icosa", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tetra", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "octa", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "mercator", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "omnimax", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fisheye", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "edwards", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "peters", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "gall", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lambert_cylindrical", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "miller_cylindrical", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lambert_azimuthal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ultra_wide_angle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera_direction", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera_location ", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "van_der_grinten", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "aitoff_hammer", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "smyth_craster", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "orthographic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera_right", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "blur_samples", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "plate_carree", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera_type", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "perspective", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mesh_camera", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "focal_point", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "balthasart", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "confidence", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "parallaxe", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hobo_dyer", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera_up", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "panoramic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "eckert_vi", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "eckert_iv", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mollweide", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "aperture", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "behrmann", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "variance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "stereo", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "icosa", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tetra", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "octa", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mercator", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "omnimax", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fisheye", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "edwards", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "peters", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gall", len)) i = len;
else i = 0;
/* If next source char is an identifier (eg. 'i' in "definate") no match */
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 772cd6bd419..4f332c09ce2 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -731,7 +731,8 @@ static int text_paste_exec(bContext *C, wmOperator *op)
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- txt_insert_buf(text, buf);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ txt_insert_buf(text, utxt, buf);
text_update_edited(text);
MEM_freeN(buf);
@@ -756,7 +757,10 @@ void TEXT_OT_paste(wmOperatorType *ot)
/* api callbacks */
ot->exec = text_paste_exec;
ot->poll = text_edit_poll;
-
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
/* properties */
RNA_def_boolean(ot->srna, "selection", 0, "Selection", "Paste text selected elsewhere rather than copied (X11 only)");
}
@@ -766,9 +770,11 @@ void TEXT_OT_paste(wmOperatorType *ot)
static int text_duplicate_line_exec(bContext *C, wmOperator *UNUSED(op))
{
Text *text = CTX_data_edit_text(C);
-
- txt_duplicate_line(text);
-
+
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+
+ txt_duplicate_line(text, utxt);
+
WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
/* run the script while editing, evil but useful */
@@ -785,10 +791,13 @@ void TEXT_OT_duplicate_line(wmOperatorType *ot)
ot->name = "Duplicate Line";
ot->idname = "TEXT_OT_duplicate_line";
ot->description = "Duplicate the current line";
-
+
/* api callbacks */
ot->exec = text_duplicate_line_exec;
ot->poll = text_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* copy operator *********************/
@@ -838,7 +847,9 @@ static int text_cut_exec(bContext *C, wmOperator *UNUSED(op))
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
txt_copy_clipboard(text);
- txt_delete_selected(text);
+
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ txt_delete_selected(text, utxt);
text_update_cursor_moved(C);
WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
@@ -860,6 +871,9 @@ void TEXT_OT_cut(wmOperatorType *ot)
/* api callbacks */
ot->exec = text_cut_exec;
ot->poll = text_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* indent operator *********************/
@@ -870,12 +884,15 @@ static int text_indent_exec(bContext *C, wmOperator *UNUSED(op))
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+
if (txt_has_sel(text)) {
txt_order_cursors(text, false);
- txt_indent(text);
+ txt_indent(text, utxt);
+ }
+ else {
+ txt_add_char(text, utxt, '\t');
}
- else
- txt_add_char(text, '\t');
text_update_edited(text);
@@ -895,6 +912,9 @@ void TEXT_OT_indent(wmOperatorType *ot)
/* api callbacks */
ot->exec = text_indent_exec;
ot->poll = text_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* unindent operator *********************/
@@ -905,8 +925,10 @@ static int text_unindent_exec(bContext *C, wmOperator *UNUSED(op))
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+
txt_order_cursors(text, false);
- txt_unindent(text);
+ txt_unindent(text, utxt);
text_update_edited(text);
@@ -926,6 +948,9 @@ void TEXT_OT_unindent(wmOperatorType *ot)
/* api callbacks */
ot->exec = text_unindent_exec;
ot->poll = text_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* line break operator *********************/
@@ -941,14 +966,15 @@ static int text_line_break_exec(bContext *C, wmOperator *UNUSED(op))
// double check tabs/spaces before splitting the line
curts = txt_setcurr_tab_spaces(text, space);
- txt_split_curline(text);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ txt_split_curline(text, utxt);
for (a = 0; a < curts; a++) {
if (text->flags & TXT_TABSTOSPACES) {
- txt_add_char(text, ' ');
+ txt_add_char(text, utxt, ' ');
}
else {
- txt_add_char(text, '\t');
+ txt_add_char(text, utxt, '\t');
}
}
@@ -961,7 +987,7 @@ static int text_line_break_exec(bContext *C, wmOperator *UNUSED(op))
text_update_cursor_moved(C);
WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_CANCELLED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_line_break(wmOperatorType *ot)
@@ -970,10 +996,13 @@ void TEXT_OT_line_break(wmOperatorType *ot)
ot->name = "Line Break";
ot->idname = "TEXT_OT_line_break";
ot->description = "Insert line break at cursor position";
-
+
/* api callbacks */
ot->exec = text_line_break_exec;
ot->poll = text_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* comment operator *********************/
@@ -985,8 +1014,10 @@ static int text_comment_exec(bContext *C, wmOperator *UNUSED(op))
if (txt_has_sel(text)) {
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+
txt_order_cursors(text, false);
- txt_comment(text);
+ txt_comment(text, utxt);
text_update_edited(text);
text_update_cursor_moved(C);
@@ -1003,10 +1034,13 @@ void TEXT_OT_comment(wmOperatorType *ot)
ot->name = "Comment";
ot->idname = "TEXT_OT_comment";
ot->description = "Convert selected text to comment";
-
+
/* api callbacks */
ot->exec = text_comment_exec;
ot->poll = text_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* uncomment operator *********************/
@@ -1018,8 +1052,10 @@ static int text_uncomment_exec(bContext *C, wmOperator *UNUSED(op))
if (txt_has_sel(text)) {
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+
txt_order_cursors(text, false);
- txt_uncomment(text);
+ txt_uncomment(text, utxt);
text_update_edited(text);
text_update_cursor_moved(C);
@@ -1041,6 +1077,9 @@ void TEXT_OT_uncomment(wmOperatorType *ot)
/* api callbacks */
ot->exec = text_uncomment_exec;
ot->poll = text_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* convert whitespace operator *********************/
@@ -1174,6 +1213,9 @@ void TEXT_OT_convert_whitespace(wmOperatorType *ot)
ot->exec = text_convert_whitespace_exec;
ot->poll = text_edit_poll;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
/* properties */
RNA_def_enum(ot->srna, "type", whitespace_type_items, TO_SPACES, "Type", "Type of whitespace to convert to");
}
@@ -1265,8 +1307,10 @@ static int move_lines_exec(bContext *C, wmOperator *op)
{
Text *text = CTX_data_edit_text(C);
const int direction = RNA_enum_get(op->ptr, "direction");
-
- txt_move_lines(text, direction);
+
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+
+ txt_move_lines(text, utxt, direction);
text_update_cursor_moved(C);
WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
@@ -1295,6 +1339,9 @@ void TEXT_OT_move_lines(wmOperatorType *ot)
ot->exec = move_lines_exec;
ot->poll = text_edit_poll;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
/* properties */
RNA_def_enum(ot->srna, "direction", direction_items, 1, "Direction", "");
}
@@ -1936,6 +1983,7 @@ static int text_delete_exec(bContext *C, wmOperator *op)
Text *text = CTX_data_edit_text(C);
int type = RNA_enum_get(op->ptr, "type");
+
text_drawcache_tag_update(st, 0);
/* behavior could be changed here,
@@ -1945,11 +1993,13 @@ static int text_delete_exec(bContext *C, wmOperator *op)
else if (type == DEL_NEXT_WORD) type = DEL_NEXT_CHAR;
}
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+
if (type == DEL_PREV_WORD) {
if (txt_cursor_is_line_start(text)) {
- txt_backspace_char(text);
+ txt_backspace_char(text, utxt);
}
- txt_backspace_word(text);
+ txt_backspace_word(text, utxt);
}
else if (type == DEL_PREV_CHAR) {
@@ -1965,13 +2015,13 @@ static int text_delete_exec(bContext *C, wmOperator *op)
}
}
- txt_backspace_char(text);
+ txt_backspace_char(text, utxt);
}
else if (type == DEL_NEXT_WORD) {
if (txt_cursor_is_line_end(text)) {
- txt_delete_char(text);
+ txt_delete_char(text, utxt);
}
- txt_delete_word(text);
+ txt_delete_word(text, utxt);
}
else if (type == DEL_NEXT_CHAR) {
@@ -1987,7 +2037,7 @@ static int text_delete_exec(bContext *C, wmOperator *op)
}
}
- txt_delete_char(text);
+ txt_delete_char(text, utxt);
}
text_update_line_edited(text->curl);
@@ -2840,16 +2890,18 @@ static int text_insert_exec(bContext *C, wmOperator *op)
str = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+
if (st && st->overwrite) {
while (str[i]) {
code = BLI_str_utf8_as_unicode_step(str, &i);
- done |= txt_replace_char(text, code);
+ done |= txt_replace_char(text, utxt, code);
}
}
else {
while (str[i]) {
code = BLI_str_utf8_as_unicode_step(str, &i);
- done |= txt_add_char(text, code);
+ done |= txt_add_char(text, utxt, code);
}
}
@@ -2919,6 +2971,9 @@ void TEXT_OT_insert(wmOperatorType *ot)
ot->invoke = text_insert_invoke;
ot->poll = text_edit_poll;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
/* properties */
prop = RNA_def_string(ot->srna, "text", NULL, 0, "Text", "Text to insert at the cursor position");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
@@ -2955,7 +3010,8 @@ static int text_find_and_replace(bContext *C, wmOperator *op, short mode)
if (found) {
if (mode == TEXT_REPLACE) {
- txt_insert_buf(text, st->replacestr);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ txt_insert_buf(text, utxt, st->replacestr);
if (text->curl && text->curl->format) {
MEM_freeN(text->curl->format);
text->curl->format = NULL;
@@ -3024,6 +3080,9 @@ void TEXT_OT_replace(wmOperatorType *ot)
/* api callbacks */
ot->exec = text_replace_exec;
ot->poll = text_space_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* find set selected *********************/
@@ -3081,6 +3140,9 @@ void TEXT_OT_replace_set_selected(wmOperatorType *ot)
/* api callbacks */
ot->exec = text_replace_set_selected_exec;
ot->poll = text_space_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/****************** resolve conflict operator ******************/
@@ -3201,26 +3263,3 @@ void TEXT_OT_to_3d_object(wmOperatorType *ot)
/* properties */
RNA_def_boolean(ot->srna, "split_lines", 0, "Split Lines", "Create one object per line in the text");
}
-
-
-/************************ undo ******************************/
-
-void ED_text_undo_step(bContext *C, int step)
-{
- Text *text = CTX_data_edit_text(C);
-
- if (!text)
- return;
-
- if (step == 1)
- txt_do_undo(text);
- else if (step == -1)
- txt_do_redo(text);
-
- text_update_edited(text);
-
- text_update_cursor_moved(C);
- text_drawcache_tag_update(CTX_wm_space_text(C), 1);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
-}
-
diff --git a/source/blender/editors/space_text/text_undo.c b/source/blender/editors/space_text/text_undo.c
new file mode 100644
index 00000000000..729522cc8f4
--- /dev/null
+++ b/source/blender/editors/space_text/text_undo.c
@@ -0,0 +1,185 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_text/text_undo.c
+ * \ingroup sptext
+ */
+
+#include <string.h>
+#include <errno.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_text_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_array_utils.h"
+
+#include "BLT_translation.h"
+
+#include "PIL_time.h"
+
+#include "BKE_context.h"
+#include "BKE_library.h"
+#include "BKE_report.h"
+#include "BKE_text.h"
+#include "BKE_undo_system.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_text.h"
+#include "ED_curve.h"
+#include "ED_screen.h"
+#include "ED_undo.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "text_intern.h"
+#include "text_format.h"
+
+/* TODO(campbell): undo_system: move text undo out of text block. */
+
+/* -------------------------------------------------------------------- */
+/** \name Implements ED Undo System
+ * \{ */
+
+typedef struct TextUndoStep {
+ UndoStep step;
+ UndoRefID_Text text_ref;
+ TextUndoBuf data;
+} TextUndoStep;
+
+static bool text_undosys_poll(bContext *C)
+{
+ Text *text = CTX_data_edit_text(C);
+ if (text == NULL) {
+ return false;
+ }
+ if (ID_IS_LINKED(text)) {
+ return false;
+ }
+ return true;
+}
+
+static void text_undosys_step_encode_init(struct bContext *C, UndoStep *us_p)
+{
+ TextUndoStep *us = (TextUndoStep *)us_p;
+ BLI_assert(BLI_array_is_zeroed(&us->data, 1));
+
+ UNUSED_VARS(C);
+ /* XXX, use to set the undo type only. */
+
+ us->data.buf = NULL;
+ us->data.len = 0;
+ us->data.pos = -1;
+}
+
+static bool text_undosys_step_encode(struct bContext *C, UndoStep *us_p)
+{
+ TextUndoStep *us = (TextUndoStep *)us_p;
+
+ Text *text = CTX_data_edit_text(C);
+
+ /* No undo data was generated. Hint, use global undo here. */
+ if ((us->data.pos == -1) || (us->data.buf == NULL)) {
+ return false;
+ }
+
+ us->text_ref.ptr = text;
+
+ us->step.data_size = us->data.len;
+
+ return true;
+}
+
+static void text_undosys_step_decode(struct bContext *C, UndoStep *us_p, int dir)
+{
+ TextUndoStep *us = (TextUndoStep *)us_p;
+ Text *text = us->text_ref.ptr;
+
+ if (dir < 0) {
+ TextUndoBuf data = us->data;
+ txt_do_undo(text, &data);
+ }
+ else {
+ TextUndoBuf data = us->data;
+ data.pos = -1;
+ txt_do_redo(text, &data);
+ }
+
+ text_update_edited(text);
+ text_update_cursor_moved(C);
+ text_drawcache_tag_update(CTX_wm_space_text(C), 1);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+}
+
+static void text_undosys_step_free(UndoStep *us_p)
+{
+ TextUndoStep *us = (TextUndoStep *)us_p;
+ MEM_SAFE_FREE(us->data.buf);
+}
+
+static void text_undosys_foreach_ID_ref(
+ UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+{
+ TextUndoStep *us = (TextUndoStep *)us_p;
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->text_ref));
+}
+
+/* Export for ED_undo_sys. */
+
+void ED_text_undosys_type(UndoType *ut)
+{
+ ut->name = "Text";
+ ut->poll = text_undosys_poll;
+ ut->step_encode_init = text_undosys_step_encode_init;
+ ut->step_encode = text_undosys_step_encode;
+ ut->step_decode = text_undosys_step_decode;
+ ut->step_free = text_undosys_step_free;
+
+ ut->step_foreach_ID_ref = text_undosys_foreach_ID_ref;
+
+ ut->mode = BKE_UNDOTYPE_MODE_ACCUMULATE;
+ ut->use_context = false;
+
+ ut->step_size = sizeof(TextUndoStep);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Utilities
+ * \{ */
+
+/* Use operator system to finish the undo step. */
+TextUndoBuf *ED_text_undo_push_init(bContext *C)
+{
+ UndoStack *ustack = ED_undo_stack_get();
+ UndoStep *us_p = BKE_undosys_step_push_init_with_type(ustack, C, NULL, BKE_UNDOSYS_TYPE_TEXT);
+ TextUndoStep *us = (TextUndoStep *)us_p;
+ return &us->data;
+}
+
+/** \} */
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index 283dbf3b4e2..42027f10fe6 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -83,7 +83,7 @@ static void time_draw_sfra_efra(Scene *scene, View2D *v2d)
/* draw darkened area outside of active timeline
* frame range used is preview range or scene range
*/
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
Gwn_VertFormat *format = immVertexFormat();
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index f8f2d5598de..0d4ec4d42d1 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -177,7 +177,7 @@ void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm, bool d
/* Draw Selected Faces */
if (me->drawflag & ME_DRAWFACES) {
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
/* dull unselected faces so as not to get in the way of seeing color */
glColor4ub(96, 96, 96, 64);
dm->drawMappedFaces(dm, draw_mesh_face_select__drawFaceOptsInv, NULL, NULL, (void *)me, DM_DRAW_SKIP_HIDDEN);
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 51dc56bafaf..93bcbc3ea0c 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -727,7 +727,7 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char
if (use_blend) {
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
Gwn_VertFormat *format = immVertexFormat();
@@ -752,8 +752,6 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char
immEnd();
immUnbindProgram();
-
- glBindTexture(GL_TEXTURE_2D, 0); /* necessary? */
}
/* Draw the image outline */
@@ -777,7 +775,7 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char
if (!use_blend) {
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
imm_draw_box_wire_2d(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
@@ -1184,7 +1182,7 @@ static void draw_transp_spot_volume(Lamp *la, float x, float z, unsigned pos)
draw_spot_cone(la, x, z, pos);
/* restore state */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
glDisable(GL_CULL_FACE);
@@ -1228,7 +1226,7 @@ static void draw_transp_sun_volume(Lamp *la, unsigned pos)
imm_draw_box(box, true, pos);
/* restore state */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
glDisable(GL_CULL_FACE);
@@ -1324,7 +1322,7 @@ void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
GPU_enable_program_point_size();
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
immUniform1f("size", lampdot_size);
@@ -4567,7 +4565,7 @@ static bool draw_mesh_object(
const char dt, const unsigned char ob_wire_col[4], const short dflag)
{
Object *ob = base->object;
- Object *obedit = scene->obedit;
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
Mesh *me = ob->data;
BMEditMesh *em = me->edit_btmesh;
bool do_alpha_after = false, drawlinked = false, retval = false;
@@ -4707,8 +4705,10 @@ static void make_color_variations(const unsigned char base_ubyte[4], float low[4
high[3] = base[3];
}
-static void draw_mesh_fancy_new(EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
- const char dt, const unsigned char ob_wire_col[4], const short dflag, const bool other_obedit)
+static void draw_mesh_fancy_new(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
+ const char dt, const unsigned char ob_wire_col[4], const short dflag, const bool other_obedit)
{
if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) {
/* too complicated! use existing methods */
@@ -5025,22 +5025,20 @@ static void draw_mesh_fancy_new(EvaluationContext *eval_ctx, Scene *scene, ViewL
dm->release(dm);
}
-static bool UNUSED_FUNCTION(draw_mesh_object_new)(const bContext *C, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
- const char dt, const unsigned char ob_wire_col[4], const short dflag)
+static bool UNUSED_FUNCTION(draw_mesh_object_new)(
+ const EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
+ const char dt, const unsigned char ob_wire_col[4], const short dflag)
{
- EvaluationContext eval_ctx;
Object *ob = base->object;
- Object *obedit = scene->obedit;
Mesh *me = ob->data;
BMEditMesh *em = me->edit_btmesh;
bool do_alpha_after = false, drawlinked = false, retval = false;
- CTX_data_eval_ctx(C, &eval_ctx);
-
if (v3d->flag2 & V3D_RENDER_SHADOW) {
/* TODO: handle shadow pass separately */
return true;
}
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(eval_ctx->view_layer);
if (obedit && ob != obedit && ob->data == obedit->data) {
if (BKE_key_from_object(ob) || BKE_key_from_object(obedit)) {}
@@ -5066,7 +5064,7 @@ static bool UNUSED_FUNCTION(draw_mesh_object_new)(const bContext *C, Scene *scen
}
else {
cageDM = editbmesh_get_derived_cage_and_final(
- &eval_ctx, scene, ob, em, scene->customdata_mask,
+ eval_ctx, scene, ob, em, scene->customdata_mask,
&finalDM);
}
@@ -5085,9 +5083,9 @@ static bool UNUSED_FUNCTION(draw_mesh_object_new)(const bContext *C, Scene *scen
DM_update_materials(cageDM, ob);
}
- const bool glsl = draw_glsl_material(scene, view_layer, ob, v3d, dt);
+ const bool glsl = draw_glsl_material(scene, eval_ctx->view_layer, ob, v3d, dt);
- GPU_begin_object_materials(v3d, rv3d, scene, view_layer, ob, glsl, NULL);
+ GPU_begin_object_materials(v3d, rv3d, scene, eval_ctx->view_layer, ob, glsl, NULL);
}
draw_em_fancy_new(scene, ar, v3d, ob, me, em, cageDM, finalDM, dt);
@@ -5103,18 +5101,18 @@ static bool UNUSED_FUNCTION(draw_mesh_object_new)(const bContext *C, Scene *scen
/* ob->bb was set by derived mesh system, do NULL check just to be sure */
if (me->totpoly <= 4 || (!ob->bb || ED_view3d_boundbox_clip(rv3d, ob->bb))) {
if (solid) {
- const bool glsl = draw_glsl_material(scene, view_layer, ob, v3d, dt);
+ const bool glsl = draw_glsl_material(scene, eval_ctx->view_layer, ob, v3d, dt);
if (dt == OB_SOLID || glsl) {
const bool check_alpha = check_alpha_pass(base);
- GPU_begin_object_materials(v3d, rv3d, scene, view_layer, ob, glsl,
+ GPU_begin_object_materials(v3d, rv3d, scene, eval_ctx->view_layer, ob, glsl,
(check_alpha) ? &do_alpha_after : NULL);
}
}
const bool other_obedit = obedit && (obedit != ob);
- draw_mesh_fancy_new(&eval_ctx, scene, view_layer, ar, v3d, rv3d, base, dt, ob_wire_col, dflag, other_obedit);
+ draw_mesh_fancy_new(eval_ctx, scene, eval_ctx->view_layer, ar, v3d, rv3d, base, dt, ob_wire_col, dflag, other_obedit);
GPU_end_object_materials();
@@ -5939,7 +5937,7 @@ static void draw_new_particle_system(
if (pars == NULL) return;
/* don't draw normal paths in edit mode */
- if (psys_in_edit_mode(eval_ctx->view_layer, psys) && (pset->flag & PE_DRAW_PART) == 0)
+ if (psys_in_edit_mode(eval_ctx->depsgraph, psys) && (pset->flag & PE_DRAW_PART) == 0)
return;
if (part->draw_as == PART_DRAW_REND)
@@ -5955,6 +5953,8 @@ static void draw_new_particle_system(
curvemapping_changed_all(psys->part->clumpcurve);
if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve)
curvemapping_changed_all(psys->part->roughcurve);
+ if ((psys->part->child_flag & PART_CHILD_USE_TWIST_CURVE) && psys->part->twistcurve)
+ curvemapping_changed_all(psys->part->twistcurve);
/* 2. */
sim.eval_ctx = eval_ctx;
@@ -6594,10 +6594,10 @@ static void draw_new_particle_system(
}
static void draw_update_ptcache_edit(
- const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, Object *ob, PTCacheEdit *edit)
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, PTCacheEdit *edit)
{
if (edit->psys && edit->psys->flag & PSYS_HAIR_UPDATED)
- PE_update_object(eval_ctx, scene, view_layer, ob, 0);
+ PE_update_object(eval_ctx, scene, ob, 0);
/* create path and child path cache if it doesn't exist already */
if (edit->pathcache == NULL) {
@@ -8322,7 +8322,8 @@ static void draw_object_selected_outline(
glDepthMask(GL_TRUE);
}
-static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const unsigned char ob_wire_col[4])
+static void draw_wire_extra(
+ RegionView3D *rv3d, Object *ob, const bool is_obedit, const unsigned char ob_wire_col[4])
{
if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL)) {
unsigned char wire_edit_col[4];
@@ -8339,13 +8340,13 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const
drawCurveDMWired(ob);
}
else {
- drawDispListwire(&ob->curve_cache->disp, ob->type, (scene->obedit == ob) ? wire_edit_col : ob_wire_col);
+ drawDispListwire(&ob->curve_cache->disp, ob->type, is_obedit ? wire_edit_col : ob_wire_col);
}
}
}
else if (ob->type == OB_MBALL) {
if (BKE_mball_is_basis(ob)) {
- drawDispListwire(&ob->curve_cache->disp, ob->type, (scene->obedit == ob) ? wire_edit_col : ob_wire_col);
+ drawDispListwire(&ob->curve_cache->disp, ob->type, is_obedit ? wire_edit_col : ob_wire_col);
}
}
@@ -8423,7 +8424,7 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data,
immUnbindProgram();
}
-void draw_object_wire_color(Scene *scene, ViewLayer *view_layer, Base *base, unsigned char r_ob_wire_col[4])
+void draw_object_wire_color(ViewLayer *view_layer, Base *base, unsigned char r_ob_wire_col[4])
{
Object *ob = base->object;
int colindex = 0;
@@ -8435,7 +8436,7 @@ void draw_object_wire_color(Scene *scene, ViewLayer *view_layer, Base *base, uns
int theme_id = is_edit ? TH_WIRE_EDIT : TH_WIRE;
int theme_shade = 0;
- if ((scene->obedit == NULL) &&
+ if (((ob->mode & OB_MODE_EDIT) == 0) &&
(G.moving & G_TRANSFORM_OBJ) &&
((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)))
{
@@ -8578,14 +8579,17 @@ void draw_object(
unsigned char _ob_wire_col[4]; /* dont initialize this */
const unsigned char *ob_wire_col = NULL; /* dont initialize this, use NULL crashes as a way to find invalid use */
bool zbufoff = false, is_paint = false, empty_object = false;
- const bool is_obact = (ob == OBACT(view_layer));
+ Object *ob_active = OBACT(view_layer);
+ const bool is_obact = (ob == ob_active);
+ /* this could be moved to a 'dflag'. */
+ const bool is_obedit = (is_obact && (ob == OBEDIT_FROM_OBACT(ob_active)));
const bool render_override = (v3d->flag2 & V3D_RENDER_OVERRIDE) != 0;
const bool is_picking = (G.f & G_PICKSEL) != 0;
const bool has_particles = (ob->particlesystem.first != NULL);
bool skip_object = false; /* Draw particles but not their emitter object. */
SmokeModifierData *smd = NULL;
- if (ob != scene->obedit) {
+ if (is_obedit == false) {
if (ob->restrictflag & OB_RESTRICT_VIEW)
return;
@@ -8666,7 +8670,7 @@ void draw_object(
/* no return after this point, otherwise leaks */
/* only once set now, will be removed too, should become a global standard */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
/* reset here to avoid having to call all over */
glLineWidth(1.0f);
@@ -8695,7 +8699,7 @@ void draw_object(
ED_view3d_project_base(ar, base);
- draw_object_wire_color(scene, view_layer, base, _ob_wire_col);
+ draw_object_wire_color(view_layer, base, _ob_wire_col);
ob_wire_col = _ob_wire_col;
//glColor3ubv(ob_wire_col);
@@ -8929,7 +8933,7 @@ afterdraw:
/* code for new particle system */
if ((ob->particlesystem.first) &&
- (ob != scene->obedit))
+ (is_obedit == false))
{
ParticleSystem *psys;
@@ -8944,7 +8948,7 @@ afterdraw:
if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) {
PTCacheEdit *edit = PE_create_current(eval_ctx, scene, ob);
if (edit && edit->psys == psys)
- draw_update_ptcache_edit(eval_ctx, scene, view_layer, ob, edit);
+ draw_update_ptcache_edit(eval_ctx, scene, ob, edit);
}
draw_new_particle_system(eval_ctx, scene, v3d, rv3d, base, psys, dt, dflag);
@@ -8959,14 +8963,14 @@ afterdraw:
/* draw edit particles last so that they can draw over child particles */
if ((dflag & DRAW_PICKING) == 0 &&
- (!scene->obedit))
+ (is_obedit == false))
{
if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) {
PTCacheEdit *edit = PE_create_current(eval_ctx, scene, ob);
if (edit) {
gpuLoadMatrix(rv3d->viewmat);
- draw_update_ptcache_edit(eval_ctx, scene, view_layer, ob, edit);
+ draw_update_ptcache_edit(eval_ctx, scene, ob, edit);
draw_ptcache_edit(scene, v3d, edit);
gpuMultMatrix(ob->obmat);
}
@@ -9108,7 +9112,7 @@ afterdraw:
}
if ((dtx & OB_DRAWWIRE) && dt >= OB_SOLID) {
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- draw_wire_extra(scene, rv3d, ob, ob_wire_col);
+ draw_wire_extra(rv3d, ob, is_obedit, ob_wire_col);
}
}
}
@@ -9212,11 +9216,11 @@ afterdraw:
immUniformColor3ubv(ob_wire_col);
/* draw hook center and offset line */
- if (ob != scene->obedit)
+ if (is_obedit == false)
draw_hooks(ob, pos);
/* help lines and so */
- if (ob != scene->obedit && ob->parent) {
+ if ((is_obedit == false) && ob->parent) {
const eObjectVisibilityCheck mode = eval_ctx->mode != DAG_EVAL_VIEWPORT ?
OB_VISIBILITY_CHECK_FOR_RENDER :
OB_VISIBILITY_CHECK_FOR_VIEWPORT;
@@ -9591,7 +9595,7 @@ static void bbs_mesh_face(BMEditMesh *em, DerivedMesh *UNUSED(dm), const bool us
GPU_select_index_get(0, &selcol);
batch = DRW_mesh_batch_cache_get_triangles_with_select_mask(me, true);
GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR_U32);
- GWN_batch_uniform_1i(batch, "color", selcol);
+ GWN_batch_uniform_1ui(batch, "color", selcol);
GWN_batch_draw(batch);
}
}
@@ -9721,7 +9725,7 @@ static void bbs_mesh_solid_verts(const EvaluationContext *UNUSED(eval_ctx), Scen
GPU_select_index_get(0, &selcol);
batch = DRW_mesh_batch_cache_get_triangles_with_select_mask(me, true);
GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR_U32);
- GWN_batch_uniform_1i(batch, "color", selcol);
+ GWN_batch_uniform_1ui(batch, "color", selcol);
GWN_batch_draw(batch);
}
@@ -9960,7 +9964,7 @@ void ED_draw_object_facemap(
immUniformColor4fv(col);
/* XXX, alpha isn't working yet, not sure why. */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
MVert *mvert;
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index fb5b9386dde..74087e6f27b 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -59,12 +59,13 @@
#include "ED_screen.h"
#include "ED_transform.h"
-#include "GPU_compositing.h"
#include "GPU_framebuffer.h"
#include "GPU_material.h"
#include "GPU_viewport.h"
#include "GPU_matrix.h"
+#include "DRW_engine.h"
+
#include "WM_api.h"
#include "WM_types.h"
#include "WM_message.h"
@@ -296,7 +297,7 @@ void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar)
}
}
-void ED_view3d_shade_update(Main *bmain, Scene *scene, View3D *v3d, ScrArea *sa)
+void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
{
wmWindowManager *wm = bmain->wm.first;
@@ -308,10 +309,6 @@ void ED_view3d_shade_update(Main *bmain, Scene *scene, View3D *v3d, ScrArea *sa)
ED_view3d_stop_render_preview(wm, ar);
}
}
- else if (scene->obedit != NULL && scene->obedit->type == OB_MESH) {
- /* Tag mesh to load edit data. */
- DEG_id_tag_update(scene->obedit->data, 0);
- }
}
/* ******************** default callbacks for view3d space ***************** */
@@ -573,14 +570,10 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar)
rv3d->gpuoffscreen = NULL;
}
- if (rv3d->compositor) {
- GPU_fx_compositor_destroy(rv3d->compositor);
- rv3d->compositor = NULL;
- }
-
if (rv3d->viewport) {
+ DRW_opengl_context_enable();
GPU_viewport_free(rv3d->viewport);
- MEM_freeN(rv3d->viewport);
+ DRW_opengl_context_disable();
rv3d->viewport = NULL;
}
}
@@ -760,12 +753,10 @@ static void view3d_main_region_free(ARegion *ar)
if (rv3d->gpuoffscreen) {
GPU_offscreen_free(rv3d->gpuoffscreen);
}
- if (rv3d->compositor) {
- GPU_fx_compositor_destroy(rv3d->compositor);
- }
if (rv3d->viewport) {
+ DRW_opengl_context_enable();
GPU_viewport_free(rv3d->viewport);
- MEM_freeN(rv3d->viewport);
+ DRW_opengl_context_disable();
}
MEM_freeN(rv3d);
@@ -922,10 +913,16 @@ static void view3d_main_region_listener(
case ND_SELECT:
{
WM_manipulatormap_tag_refresh(mmap);
- if (scene->obedit) {
- Object *ob = scene->obedit;
+
+ ID *ob_data = wmn->reference;
+ if (ob_data == NULL) {
+ BLI_assert(wmn->window); // Use `WM_event_add_notifier` instead of `WM_main_add_notifier`
+ ViewLayer *view_layer = WM_window_get_active_view_layer(wmn->window);
+ ob_data = OBEDIT_FROM_VIEW_LAYER(view_layer)->data;
+ }
+ if (ob_data) {
/* TODO(sergey): Notifiers shouldn't really be doing DEG tags. */
- DEG_id_tag_update((ID *)ob->data, DEG_TAG_SELECT_UPDATE);
+ DEG_id_tag_update(ob_data, DEG_TAG_SELECT_UPDATE);
}
ATTR_FALLTHROUGH;
}
@@ -1075,7 +1072,7 @@ static void view3d_main_region_message_subscribe(
*
* For other space types we might try avoid this, keep the 3D view as an exceptional case! */
ViewRender *view_render = BKE_viewrender_get(scene, workspace);
- wmMsgParams_RNA msg_key_params = {0};
+ wmMsgParams_RNA msg_key_params = {{{0}}};
/* Only subscribe to types. */
StructRNA *type_array[] = {
@@ -1139,9 +1136,9 @@ static void view3d_main_region_message_subscribe(
/* concept is to retrieve cursor type context-less */
static void view3d_main_region_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar))
{
- const Scene *scene = WM_window_get_active_scene(win);
-
- if (scene->obedit) {
+ ViewLayer *view_layer = WM_window_get_active_view_layer(win);
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
+ if (obedit) {
WM_cursor_set(win, CURSOR_EDIT);
}
else {
diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c
index c39057431c2..5962f1ed2ff 100644
--- a/source/blender/editors/space_view3d/view3d_camera_control.c
+++ b/source/blender/editors/space_view3d/view3d_camera_control.c
@@ -31,10 +31,10 @@
*
* Typical view-control usage:
*
- * - acquire a view-control (#ED_view3d_control_acquire).
+ * - acquire a view-control (#ED_view3d_cameracontrol_acquire).
* - modify ``rv3d->ofs``, ``rv3d->viewquat``.
- * - update the view data (#ED_view3d_control_acquire) - within a loop which draws the viewport.
- * - finish and release the view-control (#ED_view3d_control_release),
+ * - update the view data (#ED_view3d_cameracontrol_acquire) - within a loop which draws the viewport.
+ * - finish and release the view-control (#ED_view3d_cameracontrol_release),
* either keeping the current view or restoring the initial view.
*
* Notes:
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index f734bb085d0..4a0ee31a2b7 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -35,7 +35,7 @@
#include "BLI_rect.h"
#include "BLI_string.h"
#include "BLI_threads.h"
-#include "BLI_jitter.h"
+#include "BLI_jitter_2d.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -78,7 +78,6 @@
#include "GPU_immediate_util.h"
#include "GPU_material.h"
#include "GPU_viewport.h"
-#include "GPU_compositing.h"
#include "MEM_guardedalloc.h"
@@ -99,15 +98,15 @@
/* ******************** general functions ***************** */
-static bool use_depth_doit(Scene *scene, View3D *v3d)
+static bool use_depth_doit(View3D *v3d, Object *obedit)
{
if (v3d->drawtype > OB_WIRE)
return true;
/* special case (depth for wire color) */
if (v3d->drawtype <= OB_WIRE) {
- if (scene->obedit && scene->obedit->type == OB_MESH) {
- Mesh *me = scene->obedit->data;
+ if (obedit && obedit->type == OB_MESH) {
+ Mesh *me = obedit->data;
if (me->drawflag & ME_DRAWEIGHT) {
return true;
}
@@ -268,28 +267,28 @@ static void view3d_stereo3d_setup(
data = (Camera *)v3d->camera->data;
shiftx = data->shiftx;
- BLI_lock_thread(LOCK_VIEW3D);
+ BLI_thread_lock(LOCK_VIEW3D);
data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname);
BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, NULL, rect);
data->shiftx = shiftx;
- BLI_unlock_thread(LOCK_VIEW3D);
+ BLI_thread_unlock(LOCK_VIEW3D);
}
else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
float viewmat[4][4];
Object *view_ob = v3d->camera;
Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
- BLI_lock_thread(LOCK_VIEW3D);
+ BLI_thread_lock(LOCK_VIEW3D);
v3d->camera = camera;
BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, NULL, rect);
v3d->camera = view_ob;
- BLI_unlock_thread(LOCK_VIEW3D);
+ BLI_thread_unlock(LOCK_VIEW3D);
}
}
@@ -494,7 +493,7 @@ static void drawviewborder(Scene *scene, const Depsgraph *depsgraph, ARegion *ar
float alpha = 1.0f;
if (ca->passepartalpha != 1.0f) {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
alpha = ca->passepartalpha;
}
@@ -1422,7 +1421,7 @@ static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
}
}
-static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
+static void draw_view_axis(RegionView3D *rv3d, const rcti *rect)
{
const float k = U.rvisize * U.pixelsize; /* axis size */
const int bright = - 20 * (10 - U.rvibright); /* axis alpha offset (rvibright has range 0-10) */
@@ -1455,7 +1454,7 @@ static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
glLineWidth(2.0f);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -1469,6 +1468,7 @@ static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
immAttrib4ubv(col, axis_col[i]);
immVertex2f(pos, startx, starty);
+ immAttrib4ubv(col, axis_col[i]);
immVertex2fv(pos, axis_pos[i]);
}
@@ -1498,7 +1498,7 @@ static void UNUSED_FUNCTION(draw_rotation_guide)(RegionView3D *rv3d)
negate_v3_v3(o, rv3d->ofs);
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(GL_FALSE); /* don't overwrite zbuf */
Gwn_VertFormat *format = immVertexFormat();
@@ -1689,7 +1689,7 @@ static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
return name;
}
-static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect)
+static void draw_viewport_name(ARegion *ar, View3D *v3d, const rcti *rect)
{
RegionView3D *rv3d = ar->regiondata;
const char *name = view3d_get_name(v3d, rv3d);
@@ -1850,6 +1850,8 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar, const int offset)
view3d_draw_border(C, ar);
view3d_draw_grease_pencil(C);
+ BLF_batch_draw_begin();
+
if (U.uiflag & USER_SHOW_ROTVIEWICON) {
draw_view_axis(rv3d, &rect);
}
@@ -1866,6 +1868,7 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar, const int offset)
Object *ob = OBACT(view_layer);
draw_selected_name(scene, ob, &rect);
}
+
#if 0 /* TODO */
if (grid_unit) { /* draw below the viewport name */
char numstr[32] = "";
@@ -1880,6 +1883,7 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar, const int offset)
numstr[0] ? numstr : grid_unit, sizeof(numstr));
}
#endif
+ BLF_batch_draw_end();
}
static void view3d_draw_view(const bContext *C, ARegion *ar)
@@ -1916,6 +1920,13 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar)
view3d_draw_view(C, ar);
GPU_viewport_unbind(rv3d->viewport);
+ rcti rect = ar->winrct;
+ BLI_rcti_translate(&rect, -ar->winrct.xmin, -ar->winrct.ymin);
+ GPU_viewport_draw_to_screen(rv3d->viewport, &rect);
+
+ GPU_free_images_old();
+ GPU_pass_cache_garbage_collect();
+
v3d->flag |= V3D_INVALID_BACKBUF;
}
@@ -1946,9 +1957,12 @@ static void view3d_stereo3d_setup_offscreen(
}
}
-void ED_view3d_draw_offscreen_init(const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, View3D *v3d)
+void ED_view3d_draw_offscreen_init(const EvaluationContext *eval_ctx,
+ Scene *scene,
+ ViewLayer *view_layer,
+ RenderEngineType *engine_type,
+ View3D *v3d)
{
- RenderEngineType *engine_type = eval_ctx->engine_type;
if (engine_type->flag & RE_USE_LEGACY_PIPELINE) {
/* shadow buffers, before we setup matrices */
if (draw_glsl_material(scene, view_layer, NULL, v3d, v3d->drawtype)) {
@@ -1976,14 +1990,14 @@ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
* stuff like shadow buffers
*/
void ED_view3d_draw_offscreen(
- const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ const EvaluationContext *eval_ctx, Scene *scene,
+ ViewLayer *view_layer, RenderEngineType *engine_type,
View3D *v3d, ARegion *ar, int winx, int winy,
float viewmat[4][4], float winmat[4][4],
- bool do_bgpic, bool do_sky, bool is_persp, const char *viewname,
- GPUFX *fx, GPUFXSettings *fx_settings,
+ bool do_bgpic, bool do_sky, bool UNUSED(is_persp), const char *viewname,
+ GPUFXSettings *UNUSED(fx_settings),
GPUOffScreen *ofs, GPUViewport *viewport)
{
- bool do_compositing = false;
RegionView3D *rv3d = ar->regiondata;
/* set temporary new size */
@@ -2016,51 +2030,16 @@ void ED_view3d_draw_offscreen(
gpuPushMatrix();
gpuLoadIdentity();
- /* clear opengl buffers */
- if (do_sky) {
- view3d_main_region_clear(scene, v3d, ar);
- }
- else {
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- }
-
if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera)
view3d_stereo3d_setup_offscreen(eval_ctx, scene, v3d, ar, winmat, viewname);
else
view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL);
- /* XXX, should take depsgraph as arg */
- Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false);
- BLI_assert(depsgraph != NULL);
+ Depsgraph *depsgraph = eval_ctx->depsgraph;
/* main drawing call */
- RenderEngineType *engine_type = eval_ctx->engine_type;
if (engine_type->flag & RE_USE_LEGACY_PIPELINE) {
-
- /* framebuffer fx needed, we need to draw offscreen first */
- if (v3d->fx_settings.fx_flag && fx) {
- GPUSSAOSettings *ssao = NULL;
-
- if (v3d->drawtype < OB_SOLID) {
- ssao = v3d->fx_settings.ssao;
- v3d->fx_settings.ssao = NULL;
- }
-
- do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings);
-
- if (ssao)
- v3d->fx_settings.ssao = ssao;
- }
-
- VP_deprecated_view3d_draw_objects(NULL, eval_ctx, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL);
-
- /* post process */
- if (do_compositing) {
- if (!winmat)
- is_persp = rv3d->is_persp;
- GPU_fx_do_composite_pass(fx, winmat, is_persp, scene, ofs);
- }
+ VP_deprecated_view3d_draw_objects(NULL, eval_ctx, scene, v3d, ar, NULL, do_bgpic, true);
if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
/* draw grease-pencil stuff */
@@ -2076,7 +2055,9 @@ void ED_view3d_draw_offscreen(
}
}
else {
- DRW_draw_render_loop_offscreen(depsgraph, eval_ctx->engine_type, ar, v3d, do_sky, ofs, viewport);
+ DRW_draw_render_loop_offscreen(
+ depsgraph, engine_type, ar, v3d,
+ do_sky, ofs, viewport);
}
/* restore size */
@@ -2099,12 +2080,13 @@ void ED_view3d_draw_offscreen(
* (avoids re-creating when doing multiple GL renders).
*/
ImBuf *ED_view3d_draw_offscreen_imbuf(
- const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ const EvaluationContext *eval_ctx, Scene *scene,
+ ViewLayer *view_layer, RenderEngineType *engine_type,
View3D *v3d, ARegion *ar, int sizex, int sizey,
unsigned int flag, unsigned int draw_flags,
int alpha_mode, int samples, const char *viewname,
/* output vars */
- GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
+ GPUOffScreen *ofs, char err_out[256])
{
const Depsgraph *depsgraph = eval_ctx->depsgraph;
RegionView3D *rv3d = ar->regiondata;
@@ -2123,16 +2105,18 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
}
const bool own_ofs = (ofs == NULL);
+ DRW_opengl_context_enable();
if (own_ofs) {
/* bind */
- ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, false, err_out);
+ ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, true, false, err_out);
if (ofs == NULL) {
+ DRW_opengl_context_disable();
return NULL;
}
}
- ED_view3d_draw_offscreen_init(eval_ctx, scene, view_layer, v3d);
+ ED_view3d_draw_offscreen_init(eval_ctx, scene, view_layer, engine_type, v3d);
GPU_offscreen_bind(ofs, true);
@@ -2174,9 +2158,10 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
if ((samples && use_full_sample) == 0) {
/* Single-pass render, common case */
ED_view3d_draw_offscreen(
- eval_ctx, scene, view_layer, v3d, ar, sizex, sizey, NULL, winmat,
+ eval_ctx, scene, view_layer, engine_type,
+ v3d, ar, sizex, sizey, NULL, winmat,
draw_background, draw_sky, !is_ortho, viewname,
- fx, &fx_settings, ofs, NULL);
+ &fx_settings, ofs, NULL);
if (ibuf->rect_float) {
GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
@@ -2198,9 +2183,10 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
/* first sample buffer, also initializes 'rv3d->persmat' */
ED_view3d_draw_offscreen(
- eval_ctx, scene, view_layer, v3d, ar, sizex, sizey, NULL, winmat,
+ eval_ctx, scene, view_layer, engine_type,
+ v3d, ar, sizex, sizey, NULL, winmat,
draw_background, draw_sky, !is_ortho, viewname,
- fx, &fx_settings, ofs, viewport);
+ &fx_settings, ofs, viewport);
GPU_offscreen_read_pixels(ofs, GL_FLOAT, accum_buffer);
/* skip the first sample */
@@ -2212,9 +2198,10 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
(jit_ofs[j][1] * 2.0f) / sizey);
ED_view3d_draw_offscreen(
- eval_ctx, scene, view_layer, v3d, ar, sizex, sizey, NULL, winmat_jitter,
+ eval_ctx, scene, view_layer, engine_type,
+ v3d, ar, sizex, sizey, NULL, winmat_jitter,
draw_background, draw_sky, !is_ortho, viewname,
- fx, &fx_settings, ofs, viewport);
+ &fx_settings, ofs, viewport);
GPU_offscreen_read_pixels(ofs, GL_FLOAT, rect_temp);
unsigned int i = sizex * sizey * 4;
@@ -2227,7 +2214,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
/* don't free data owned by 'ofs' */
GPU_viewport_clear_from_offscreen(viewport);
GPU_viewport_free(viewport);
- MEM_freeN(viewport);
}
if (ibuf->rect_float == NULL) {
@@ -2259,6 +2245,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
GPU_offscreen_free(ofs);
}
+ DRW_opengl_context_disable();
+
if (ibuf->rect_float && ibuf->rect)
IMB_rect_from_float(ibuf);
@@ -2274,11 +2262,12 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
* \note used by the sequencer
*/
ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
- const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ const EvaluationContext *eval_ctx, Scene *scene,
+ ViewLayer *view_layer, RenderEngineType *engine_type,
Object *camera, int width, int height,
unsigned int flag, unsigned int draw_flags, int drawtype,
int alpha_mode, int samples, const char *viewname,
- GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
+ GPUOffScreen *ofs, char err_out[256])
{
View3D v3d = {NULL};
ARegion ar = {NULL};
@@ -2336,8 +2325,9 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
invert_m4_m4(rv3d.persinv, rv3d.viewinv);
return ED_view3d_draw_offscreen_imbuf(
- eval_ctx, scene, view_layer, &v3d, &ar, width, height, flag,
- draw_flags, alpha_mode, samples, viewname, fx, ofs, err_out);
+ eval_ctx, scene, view_layer, engine_type,
+ &v3d, &ar, width, height, flag,
+ draw_flags, alpha_mode, samples, viewname, ofs, err_out);
}
/** \} */
@@ -2359,12 +2349,12 @@ void VP_legacy_drawcursor(Scene *scene, ViewLayer *view_layer, ARegion *ar, View
}
}
-void VP_legacy_draw_view_axis(RegionView3D *rv3d, rcti *rect)
+void VP_legacy_draw_view_axis(RegionView3D *rv3d, const rcti *rect)
{
draw_view_axis(rv3d, rect);
}
-void VP_legacy_draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect)
+void VP_legacy_draw_viewport_name(ARegion *ar, View3D *v3d, const rcti *rect)
{
draw_viewport_name(ar, v3d, rect);
}
@@ -2401,9 +2391,9 @@ void VP_legacy_view3d_stereo3d_setup(const EvaluationContext *eval_ctx, Scene *s
view3d_stereo3d_setup(eval_ctx, scene, v3d, ar, NULL);
}
-bool VP_legacy_use_depth(Scene *scene, View3D *v3d)
+bool VP_legacy_use_depth(View3D *v3d, Object *obedit)
{
- return use_depth_doit(scene, v3d);
+ return use_depth_doit(v3d, obedit);
}
void VP_drawviewborder(Scene *scene, const struct Depsgraph *depsgraph, ARegion *ar, View3D *v3d)
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index 7cb362ffb92..7272fc6b408 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -48,7 +48,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLI_jitter.h"
+#include "BLI_jitter_2d.h"
#include "BLI_utildefines.h"
#include "BLI_endian_switch.h"
#include "BLI_threads.h"
@@ -100,7 +100,6 @@
#include "GPU_framebuffer.h"
#include "GPU_lamp.h"
#include "GPU_material.h"
-#include "GPU_compositing.h"
#include "GPU_extensions.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
@@ -202,7 +201,7 @@ static void draw_view_icon(RegionView3D *rv3d, rcti *rect)
else return;
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
UI_icon_draw(5.0 + rect->xmin, 5.0 + rect->ymin, icon);
@@ -211,31 +210,32 @@ static void draw_view_icon(RegionView3D *rv3d, rcti *rect)
/* *********************** backdraw for selection *************** */
-static void backdrawview3d(const struct EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, wmWindow *win, ARegion *ar, View3D *v3d)
+static void backdrawview3d(
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ ARegion *ar, View3D *v3d,
+ Object *obact, Object *obedit)
{
RegionView3D *rv3d = ar->regiondata;
- struct Base *base = view_layer->basact;
- int multisample_enabled;
BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
- if (base && (base->object->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) ||
- BKE_paint_select_face_test(base->object)))
+ if (obact && (obact->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) ||
+ BKE_paint_select_face_test(obact)))
{
/* do nothing */
}
/* texture paint mode sampling */
- else if (base && (base->object->mode & OB_MODE_TEXTURE_PAINT) &&
+ else if (obact && (obact->mode & OB_MODE_TEXTURE_PAINT) &&
(v3d->drawtype > OB_WIRE))
{
/* do nothing */
}
- else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) &&
+ else if ((obact && (obact->mode & OB_MODE_PARTICLE_EDIT)) &&
V3D_IS_ZBUF(v3d))
{
/* do nothing */
}
- else if (scene->obedit &&
+ else if ((obedit && (obedit->mode & OB_MODE_EDIT)) &&
V3D_IS_ZBUF(v3d))
{
/* do nothing */
@@ -262,14 +262,13 @@ static void backdrawview3d(const struct EvaluationContext *eval_ctx, Scene *scen
/* dithering and AA break color coding, so disable */
glDisable(GL_DITHER);
- multisample_enabled = glIsEnabled(GL_MULTISAMPLE);
- if (multisample_enabled)
- glDisable(GL_MULTISAMPLE);
-
- if (win->multisamples != USER_MULTISAMPLE_NONE) {
+ if (false) {
/* for multisample we use an offscreen FBO. multisample drawing can fail
* with color coded selection drawing, and reading back depths from such
- * a buffer can also cause a few seconds freeze on OS X / NVidia. */
+ * a buffer can also cause a few seconds freeze on OS X / NVidia.
+ *
+ * NOTE: code is no longer used now, but offscreen drawing is likely
+ * what we will always want to do for the new viewport. */
int w = BLI_rcti_size_x(&ar->winrct);
int h = BLI_rcti_size_y(&ar->winrct);
char error[256];
@@ -284,7 +283,7 @@ static void backdrawview3d(const struct EvaluationContext *eval_ctx, Scene *scen
}
if (!rv3d->gpuoffscreen) {
- rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, false, error);
+ rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, true, false, error);
if (!rv3d->gpuoffscreen)
fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error);
@@ -310,10 +309,11 @@ static void backdrawview3d(const struct EvaluationContext *eval_ctx, Scene *scen
ED_view3d_clipping_set(rv3d);
G.f |= G_BACKBUFSEL;
-
- if (base && ((base->flag & BASE_VISIBLED) != 0))
- draw_object_backbufsel(eval_ctx, scene, v3d, rv3d, base->object);
-
+
+ if (obact && ((obact->base_flag & BASE_VISIBLED) != 0)) {
+ draw_object_backbufsel(eval_ctx, scene, v3d, rv3d, obact);
+ }
+
if (rv3d->gpuoffscreen)
GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
else
@@ -325,8 +325,6 @@ static void backdrawview3d(const struct EvaluationContext *eval_ctx, Scene *scen
v3d->zbuf = false;
glDisable(GL_DEPTH_TEST);
glEnable(GL_DITHER);
- if (multisample_enabled)
- glEnable(GL_MULTISAMPLE);
if (rv3d->rflag & RV3D_CLIPPING)
ED_view3d_clipping_disable();
@@ -356,7 +354,7 @@ static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h,
void ED_view3d_backbuf_validate(const struct EvaluationContext *eval_ctx, ViewContext *vc)
{
if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
- backdrawview3d(eval_ctx, vc->scene, vc->view_layer, vc->win, vc->ar, vc->v3d);
+ backdrawview3d(eval_ctx, vc->scene, vc->ar, vc->v3d, vc->obact, vc->obedit);
}
}
@@ -734,7 +732,7 @@ static void view3d_draw_bgpic(Scene *scene, const Depsgraph *depsgraph,
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
gpuPushProjectionMatrix();
gpuPushMatrix();
@@ -1302,7 +1300,7 @@ void ED_view3d_draw_select_loop(
for (base = view_layer->object_bases.first; base; base = base->next) {
if ((base->flag & BASE_VISIBLED) != 0) {
if (((base->flag & BASE_SELECTABLED) == 0) ||
- (use_obedit_skip && (scene->obedit->data == base->object->data)))
+ (use_obedit_skip && (vc->obedit->data == base->object->data)))
{
base->object->select_color = 0;
}
@@ -1422,11 +1420,14 @@ static void gpu_update_lamps_shadows_world(const EvaluationContext *eval_ctx, Sc
mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
invert_m4_m4(rv3d.persinv, rv3d.viewinv);
+ RenderEngineType *engine_type = RE_engines_find(scene->view_render.engine_id);
+
/* no need to call ED_view3d_draw_offscreen_init since shadow buffers were already updated */
ED_view3d_draw_offscreen(
- eval_ctx, scene, eval_ctx->view_layer, v3d, &ar, winsize, winsize, viewmat, winmat,
+ eval_ctx, scene, eval_ctx->view_layer, engine_type,
+ v3d, &ar, winsize, winsize, viewmat, winmat,
false, false, true,
- NULL, NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL);
GPU_lamp_shadow_buffer_unbind(shadow->lamp);
v3d->drawtype = drawtype;
@@ -1500,18 +1501,18 @@ static void view3d_draw_objects(
const EvaluationContext *eval_ctx,
Scene *scene, View3D *v3d, ARegion *ar,
const char **grid_unit,
- const bool do_bgpic, const bool draw_offscreen, GPUFX *fx)
+ const bool do_bgpic, const bool draw_offscreen)
{
ViewLayer *view_layer = C ? CTX_data_view_layer(C) : BKE_view_layer_from_scene_get(scene);
Depsgraph *depsgraph = CTX_data_depsgraph(C);
RegionView3D *rv3d = ar->regiondata;
Base *base;
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
const bool do_camera_frame = !draw_offscreen;
const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0;
const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO);
/* only draw grids after in solid modes, else it hovers over mesh wires */
- const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE) && fx;
- bool do_composite_xray = false;
+ const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE);
bool xrayclear = true;
if (!draw_offscreen) {
@@ -1522,7 +1523,7 @@ static void view3d_draw_objects(
view3d_draw_clipping(rv3d);
/* set zbuffer after we draw clipping region */
- v3d->zbuf = VP_legacy_use_depth(scene, v3d);
+ v3d->zbuf = VP_legacy_use_depth(v3d, obedit);
if (v3d->zbuf) {
glEnable(GL_DEPTH_TEST);
@@ -1599,7 +1600,7 @@ static void view3d_draw_objects(
draw_dupli_objects(eval_ctx, scene, view_layer, ar, v3d, base);
}
if ((base->flag & BASE_SELECTED) == 0) {
- if (base->object != scene->obedit)
+ if (base->object != obedit)
draw_object(eval_ctx, scene, view_layer, ar, v3d, base, 0);
}
}
@@ -1611,7 +1612,7 @@ static void view3d_draw_objects(
/* draw selected and editmode */
for (base = view_layer->object_bases.first; base; base = base->next) {
if ((base->flag & BASE_VISIBLED) != 0) {
- if (base->object == scene->obedit || (base->flag & BASE_SELECTED)) {
+ if (base->object == obedit || (base->flag & BASE_SELECTED)) {
draw_object(eval_ctx, scene, view_layer, ar, v3d, base, 0);
}
}
@@ -1636,19 +1637,9 @@ static void view3d_draw_objects(
/* transp and X-ray afterdraw stuff */
if (v3d->afterdraw_transp.first) view3d_draw_transp(eval_ctx, scene, view_layer, ar, v3d);
- /* always do that here to cleanup depth buffers if none needed */
- if (fx) {
- do_composite_xray = v3d->zbuf && (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first);
- GPU_fx_compositor_setup_XRay_pass(fx, do_composite_xray);
- }
-
if (v3d->afterdraw_xray.first) view3d_draw_xray(eval_ctx, scene, view_layer, ar, v3d, &xrayclear);
if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(eval_ctx, scene, view_layer, ar, v3d, xrayclear);
- if (fx && do_composite_xray) {
- GPU_fx_compositor_XRay_resolve(fx);
- }
-
if (!draw_offscreen) {
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
}
@@ -1956,9 +1947,6 @@ static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, Vie
CTX_data_eval_ctx(C, &eval_ctx);
- /* post processing */
- bool do_compositing = false;
-
/* shadow buffers, before we setup matrices */
if (draw_glsl_material(scene, view_layer, NULL, v3d, v3d->drawtype))
gpu_update_lamps_shadows_world(&eval_ctx, scene, v3d);
@@ -1986,40 +1974,9 @@ static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, Vie
update_lods(scene, rv3d->viewinv[3]);
}
#endif
-
- /* framebuffer fx needed, we need to draw offscreen first */
- if (v3d->fx_settings.fx_flag && v3d->drawtype >= OB_SOLID) {
- BKE_screen_gpu_fx_validate(&v3d->fx_settings);
- GPUFXSettings fx_settings = v3d->fx_settings;
- if (!rv3d->compositor)
- rv3d->compositor = GPU_fx_compositor_create();
-
- if (rv3d->persp == RV3D_CAMOB && v3d->camera)
- BKE_camera_to_gpu_dof(v3d->camera, &fx_settings);
- else {
- fx_settings.dof = NULL;
- }
-
- do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings);
- }
- /* enables anti-aliasing for 3D view drawing */
- if (win->multisamples != USER_MULTISAMPLE_NONE) {
- glEnable(GL_MULTISAMPLE);
- }
-
/* main drawing call */
- view3d_draw_objects(C, &eval_ctx, scene, v3d, ar, grid_unit, true, false, do_compositing ? rv3d->compositor : NULL);
-
- /* post process */
- if (do_compositing) {
- GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL);
- }
-
- /* Disable back anti-aliasing */
- if (win->multisamples != USER_MULTISAMPLE_NONE) {
- glDisable(GL_MULTISAMPLE);
- }
+ view3d_draw_objects(C, &eval_ctx, scene, v3d, ar, grid_unit, true, false);
if (v3d->lay_used != lay_used) { /* happens when loading old files or loading with UI load */
/* find header and force tag redraw */
@@ -2176,9 +2133,9 @@ void VP_deprecated_view3d_draw_objects(
const EvaluationContext *eval_ctx,
Scene *scene, View3D *v3d, ARegion *ar,
const char **grid_unit,
- const bool do_bgpic, const bool draw_offscreen, GPUFX *fx)
+ const bool do_bgpic, const bool draw_offscreen)
{
- view3d_draw_objects(C, eval_ctx, scene, v3d, ar, grid_unit, do_bgpic, draw_offscreen, fx);
+ view3d_draw_objects(C, eval_ctx, scene, v3d, ar, grid_unit, do_bgpic, draw_offscreen);
}
void VP_deprecated_gpu_update_lamps_shadows_world(const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d)
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 1e368e2d171..0ae69debf18 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -57,6 +57,7 @@
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_report.h"
+#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_action.h"
@@ -77,61 +78,123 @@
#include "ED_gpencil.h"
#include "ED_view3d.h"
-
#include "UI_resources.h"
-#include "PIL_time.h" /* smoothview */
+#include "PIL_time.h"
#include "view3d_intern.h" /* own include */
/* -------------------------------------------------------------------- */
+/** \name Generic View Operator Properties
+ * \{ */
+
+enum eV3D_OpPropFlag {
+ V3D_OP_PROP_MOUSE_CO = (1 << 0),
+ V3D_OP_PROP_DELTA = (1 << 1),
+ V3D_OP_PROP_USE_ALL_REGIONS = (1 << 2),
+ V3D_OP_PROP_USE_MOUSE_INIT = (1 << 3),
+};
+
+static void view3d_operator_properties_common(wmOperatorType *ot, const enum eV3D_OpPropFlag flag)
+{
+ if (flag & V3D_OP_PROP_MOUSE_CO) {
+ PropertyRNA *prop;
+ prop = RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Region Position X", "", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Region Position Y", "", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
+ if (flag & V3D_OP_PROP_DELTA) {
+ RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
+ }
+ if (flag & V3D_OP_PROP_USE_ALL_REGIONS) {
+ PropertyRNA *prop;
+ prop = RNA_def_boolean(ot->srna, "use_all_regions", 0, "All Regions", "View selected for all regions");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ }
+ if (flag & V3D_OP_PROP_USE_MOUSE_INIT) {
+ /* Disable when view operators are initialized from buttons. */
+ PropertyRNA *prop;
+ prop = RNA_def_boolean(ot->srna, "use_mouse_init", true, "Mouse Init", "Use initial mouse position");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Generic View Operator Custom-Data
* \{ */
typedef struct ViewOpsData {
- /* context pointers (assigned by viewops_data_alloc) */
- const Depsgraph *depsgraph;
+ /** Context pointers (assigned by #viewops_data_alloc). */
Scene *scene;
ScrArea *sa;
ARegion *ar;
View3D *v3d;
RegionView3D *rv3d;
+ Depsgraph *depsgraph;
- /* needed for continuous zoom */
+ /** Needed for continuous zoom. */
wmTimer *timer;
- double timer_lastdraw;
- float oldquat[4];
- float viewquat[4]; /* working copy of rv3d->viewquat */
- float trackvec[3];
- float mousevec[3]; /* dolly only */
+ /** Viewport state on initialization, don't change afterwards. */
+ struct {
+ float dist;
+ float camzoom;
+ float quat[4];
+ /** #wmEvent.x, y. */
+ int event_xy[2];
+ /** Offset to use when #VIEWOPS_FLAG_USE_MOUSE_INIT is not set.
+ * so we can simulate pressing in the middle of the screen. */
+ int event_xy_offset[2];
+ /** #wmEvent.type that triggered the operator. */
+ int event_type;
+ float ofs[3];
+ /** Initial distance to 'ofs'. */
+ float zfac;
+
+ /** Trackball rotation only. */
+ float trackvec[3];
+ /** Dolly only. */
+ float mousevec[3];
+ } init;
+
+ /** Previous state (previous modal event handled). */
+ struct {
+ int event_xy[2];
+ /** For operators that use time-steps (continuous zoom). */
+ double time;
+ } prev;
+
+ /** Current state. */
+ struct {
+ /** Working copy of #RegionView3D.viewquat, needed for rotation calculation
+ * so we can apply snap to the view-port while keeping the unsnapped rotation
+ * here to use when snap is disabled and for continued calculation. */
+ float viewquat[4];
+ } curr;
+
float reverse;
- float dist_prev, camzoom_prev;
- float grid, far;
bool axis_snap; /* view rotate only */
- float zfac;
- /* use for orbit selection and auto-dist */
- float ofs[3], dyn_ofs[3];
+ /** Use for orbit selection and auto-dist. */
+ float dyn_ofs[3];
bool use_dyn_ofs;
-
- int origx, origy, oldx, oldy;
- int origkey; /* the key that triggered the operator */
-
} ViewOpsData;
#define TRACKBALLSIZE (1.1f)
-static void calctrackballvec(const rcti *rect, int mx, int my, float vec[3])
+static void calctrackballvec(const rcti *rect, const int event_xy[2], float vec[3])
{
const float radius = TRACKBALLSIZE;
const float t = radius / (float)M_SQRT2;
float x, y, z, d;
/* normalize x and y */
- x = BLI_rcti_cent_x(rect) - mx;
+ x = BLI_rcti_cent_x(rect) - event_xy[0];
x /= (float)(BLI_rcti_size_x(rect) / 4);
- y = BLI_rcti_cent_y(rect) - my;
+ y = BLI_rcti_cent_y(rect) - event_xy[1];
y /= (float)(BLI_rcti_size_y(rect) / 2);
d = sqrtf(x * x + y * y);
if (d < t) { /* Inside sphere */
@@ -164,7 +227,7 @@ static void viewops_data_alloc(bContext *C, wmOperator *op)
}
void view3d_orbit_apply_dyn_ofs(
- float r_ofs[3], const float ofs_old[3], const float viewquat_old[4],
+ float r_ofs[3], const float ofs_init[3], const float viewquat_old[4],
const float viewquat_new[4], const float dyn_ofs[3])
{
float q[4];
@@ -173,7 +236,7 @@ void view3d_orbit_apply_dyn_ofs(
invert_qt_normalized(q);
- sub_v3_v3v3(r_ofs, ofs_old, dyn_ofs);
+ sub_v3_v3v3(r_ofs, ofs_init, dyn_ofs);
mul_qt_v3(q, r_ofs);
add_v3_v3(r_ofs, dyn_ofs);
}
@@ -262,48 +325,58 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
return is_set;
}
-enum eViewOpsOrbit {
- VIEWOPS_ORBIT_SELECT = (1 << 0),
- VIEWOPS_ORBIT_DEPTH = (1 << 1),
+enum eViewOpsFlag {
+ /** When enabled, rotate around the selection. */
+ VIEWOPS_FLAG_ORBIT_SELECT = (1 << 0),
+ /** When enabled, use the depth under the cursor for navigation. */
+ VIEWOPS_FLAG_DEPTH_NAVIGATE = (1 << 1),
+ /**
+ * When enabled run #ED_view3d_persp_ensure this may switch out of
+ * camera view when orbiting or switch from ortho to perspective when auto-persp is enabled.
+ * Some operations don't require this (view zoom/pan or ndof where subtle rotation is common
+ * so we don't want it to trigger auto-perspective). */
+ VIEWOPS_FLAG_PERSP_ENSURE = (1 << 2),
+ /** When set, ignore any options that depend on initial cursor location. */
+ VIEWOPS_FLAG_USE_MOUSE_INIT = (1 << 3),
};
-static enum eViewOpsOrbit viewops_orbit_mode_ex(bool use_select, bool use_depth)
+static enum eViewOpsFlag viewops_flag_from_args(bool use_select, bool use_depth)
{
- enum eViewOpsOrbit flag = 0;
+ enum eViewOpsFlag flag = 0;
if (use_select) {
- flag |= VIEWOPS_ORBIT_SELECT;
+ flag |= VIEWOPS_FLAG_ORBIT_SELECT;
}
if (use_depth) {
- flag |= VIEWOPS_ORBIT_DEPTH;
+ flag |= VIEWOPS_FLAG_DEPTH_NAVIGATE;
}
return flag;
}
-static enum eViewOpsOrbit viewops_orbit_mode(void)
+static enum eViewOpsFlag viewops_flag_from_prefs(void)
{
- return viewops_orbit_mode_ex(
+ return viewops_flag_from_args(
(U.uiflag & USER_ORBIT_SELECTION) != 0,
- (U.uiflag & USER_ZBUF_ORBIT) != 0);
+ (U.uiflag & USER_DEPTH_NAVIGATE) != 0);
}
/**
* Calculate the values for #ViewOpsData
- *
- * \param use_ensure_persp: When enabled run #ED_view3d_persp_ensure this may switch out of
- * camera view when orbiting or switch from ortho to perspective when auto-persp is enabled.
- * Some operations don't require this (view zoom/pan or ndof where subtle rotation is common
- * so we don't want it to trigger auto-perspective).
*/
-static void viewops_data_create_ex(
+static void viewops_data_create(
bContext *C, wmOperator *op, const wmEvent *event,
- bool use_ensure_persp, enum eViewOpsOrbit orbit_mode)
+ enum eViewOpsFlag viewops_flag)
{
ViewOpsData *vod = op->customdata;
RegionView3D *rv3d = vod->rv3d;
+ /* Could do this more nicely. */
+ if ((viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) == 0) {
+ viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE;
+ }
+
/* we need the depth info before changing any viewport options */
- if (orbit_mode & VIEWOPS_ORBIT_DEPTH) {
+ if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) {
EvaluationContext eval_ctx;
struct Depsgraph *graph = CTX_data_depsgraph(C);
float fallback_depth_pt[3];
@@ -322,7 +395,7 @@ static void viewops_data_create_ex(
vod->use_dyn_ofs = false;
}
- if (use_ensure_persp) {
+ if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) {
if (ED_view3d_persp_ensure(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
@@ -336,25 +409,37 @@ static void viewops_data_create_ex(
* we may want to make this optional but for now its needed always */
ED_view3d_camera_lock_init(vod->v3d, vod->rv3d);
- vod->dist_prev = rv3d->dist;
- vod->camzoom_prev = rv3d->camzoom;
- copy_qt_qt(vod->viewquat, rv3d->viewquat);
- copy_qt_qt(vod->oldquat, rv3d->viewquat);
- vod->origx = vod->oldx = event->x;
- vod->origy = vod->oldy = event->y;
- vod->origkey = event->type; /* the key that triggered the operator. */
- copy_v3_v3(vod->ofs, rv3d->ofs);
+ vod->init.dist = rv3d->dist;
+ vod->init.camzoom = rv3d->camzoom;
+ copy_qt_qt(vod->init.quat, rv3d->viewquat);
+ vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x;
+ vod->init.event_xy[1] = vod->prev.event_xy[1] = event->y;
- if (orbit_mode & VIEWOPS_ORBIT_SELECT) {
+ if (viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) {
+ vod->init.event_xy_offset[0] = 0;
+ vod->init.event_xy_offset[1] = 0;
+ }
+ else {
+ /* Simulate the event starting in the middle of the region. */
+ vod->init.event_xy_offset[0] = BLI_rcti_cent_x(&vod->ar->winrct) - event->x;
+ vod->init.event_xy_offset[1] = BLI_rcti_cent_y(&vod->ar->winrct) - event->y;
+ }
+
+ vod->init.event_type = event->type;
+ copy_v3_v3(vod->init.ofs, rv3d->ofs);
+
+ copy_qt_qt(vod->curr.viewquat, rv3d->viewquat);
+
+ if (viewops_flag & VIEWOPS_FLAG_ORBIT_SELECT) {
float ofs[3];
if (view3d_orbit_calc_center(C, ofs) || (vod->use_dyn_ofs == false)) {
vod->use_dyn_ofs = true;
negate_v3_v3(vod->dyn_ofs, ofs);
- orbit_mode &= ~VIEWOPS_ORBIT_DEPTH;
+ viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE;
}
}
- if (orbit_mode & VIEWOPS_ORBIT_DEPTH) {
+ if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) {
if (vod->use_dyn_ofs) {
if (rv3d->is_persp) {
float my_origin[3]; /* original G.vd->ofs */
@@ -381,7 +466,7 @@ static void viewops_data_create_ex(
/* find a new ofs value that is along the view axis (rather than the mouse location) */
closest_to_line_v3(dvec, vod->dyn_ofs, my_pivot, my_origin);
- vod->dist_prev = rv3d->dist = len_v3v3(my_pivot, dvec);
+ vod->init.dist = rv3d->dist = len_v3v3(my_pivot, dvec);
negate_v3_v3(rv3d->ofs, dvec);
}
@@ -394,27 +479,26 @@ static void viewops_data_create_ex(
negate_v3(rv3d->ofs);
}
negate_v3(vod->dyn_ofs);
- copy_v3_v3(vod->ofs, rv3d->ofs);
+ copy_v3_v3(vod->init.ofs, rv3d->ofs);
}
}
+ /* For dolly */
+ ED_view3d_win_to_vector(vod->ar, (const float[2]){UNPACK2(event->mval)}, vod->init.mousevec);
+
{
- /* for dolly */
- const float mval_f[2] = {(float)event->mval[0],
- (float)event->mval[1]};
- ED_view3d_win_to_vector(vod->ar, mval_f, vod->mousevec);
+ const int event_xy_offset[2] = {
+ event->x + vod->init.event_xy_offset[0],
+ event->y + vod->init.event_xy_offset[1],
+ };
+ /* For rotation with trackball rotation. */
+ calctrackballvec(&vod->ar->winrct, event_xy_offset, vod->init.trackvec);
}
- /* lookup, we don't pass on v3d to prevent confusement */
- vod->grid = vod->v3d->grid;
- vod->far = vod->v3d->far;
-
- calctrackballvec(&vod->ar->winrct, event->x, event->y, vod->trackvec);
-
{
float tvec[3];
negate_v3_v3(tvec, rv3d->ofs);
- vod->zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL);
+ vod->init.zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL);
}
vod->reverse = 1.0f;
@@ -424,12 +508,6 @@ static void viewops_data_create_ex(
rv3d->rflag |= RV3D_NAVIGATING;
}
-static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *event, bool use_ensure_persp)
-{
- enum eViewOpsOrbit orbit_mode = viewops_orbit_mode();
- viewops_data_create_ex(C, op, event, use_ensure_persp, orbit_mode);
-}
-
static void viewops_data_free(bContext *C, wmOperator *op)
{
ARegion *ar;
@@ -487,7 +565,7 @@ void viewrotate_modal_keymap(wmKeyConfig *keyconf)
{VIEWROT_MODAL_AXIS_SNAP_ENABLE, "AXIS_SNAP_ENABLE", 0, "Enable Axis Snap", ""},
{VIEWROT_MODAL_AXIS_SNAP_DISABLE, "AXIS_SNAP_DISABLE", 0, "Disable Axis Snap", ""},
-
+
{VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"},
{VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
@@ -514,17 +592,16 @@ void viewrotate_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
#endif
-
+
/* assign map to operators */
WM_modalkeymap_assign(keymap, "VIEW3D_OT_rotate");
-
}
static void viewrotate_apply_dyn_ofs(ViewOpsData *vod, const float viewquat_new[4])
{
if (vod->use_dyn_ofs) {
RegionView3D *rv3d = vod->rv3d;
- view3d_orbit_apply_dyn_ofs(rv3d->ofs, vod->ofs, vod->oldquat, viewquat_new, vod->dyn_ofs);
+ view3d_orbit_apply_dyn_ofs(rv3d->ofs, vod->init.ofs, vod->init.quat, viewquat_new, vod->dyn_ofs);
}
}
@@ -540,7 +617,7 @@ static void viewrotate_apply_snap(ViewOpsData *vod)
int x, y, z;
bool found = false;
- invert_qt_qt_normalized(viewquat_inv, vod->viewquat);
+ invert_qt_qt_normalized(viewquat_inv, vod->curr.viewquat);
mul_qt_v3(viewquat_inv, zaxis);
normalize_v3(zaxis);
@@ -576,7 +653,7 @@ static void viewrotate_apply_snap(ViewOpsData *vod)
* for testing roll */
rotation_between_vecs_to_quat(viewquat_align, zaxis_best, zaxis);
normalize_qt(viewquat_align);
- mul_qt_qtqt(viewquat_align, vod->viewquat, viewquat_align);
+ mul_qt_qtqt(viewquat_align, vod->curr.viewquat, viewquat_align);
normalize_qt(viewquat_align);
invert_qt_qt_normalized(viewquat_align_inv, viewquat_align);
@@ -630,7 +707,7 @@ static void viewrotate_apply_snap(ViewOpsData *vod)
}
}
-static void viewrotate_apply(ViewOpsData *vod, int x, int y)
+static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2])
{
RegionView3D *rv3d = vod->rv3d;
@@ -640,9 +717,15 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y)
float axis[3], q1[4], dvec[3], newvec[3];
float angle;
- calctrackballvec(&vod->ar->winrct, x, y, newvec);
+ {
+ const int event_xy_offset[2] = {
+ event_xy[0] + vod->init.event_xy_offset[0],
+ event_xy[1] + vod->init.event_xy_offset[1],
+ };
+ calctrackballvec(&vod->ar->winrct, event_xy_offset, newvec);
+ }
- sub_v3_v3v3(dvec, newvec, vod->trackvec);
+ sub_v3_v3v3(dvec, newvec, vod->init.trackvec);
angle = (len_v3(dvec) / (2.0f * TRACKBALLSIZE)) * (float)M_PI;
@@ -653,12 +736,12 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y)
* so that the angle of rotation is linearly proportional to
* the distance that the mouse is dragged. */
- cross_v3_v3v3(axis, vod->trackvec, newvec);
+ cross_v3_v3v3(axis, vod->init.trackvec, newvec);
axis_angle_to_quat(q1, axis, angle);
- mul_qt_qtqt(vod->viewquat, q1, vod->oldquat);
+ mul_qt_qtqt(vod->curr.viewquat, q1, vod->init.quat);
- viewrotate_apply_dyn_ofs(vod, vod->viewquat);
+ viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat);
}
else {
/* New turntable view code by John Aughey */
@@ -675,7 +758,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y)
const float sensitivity = 0.007f;
/* Get the 3x3 matrix and its inverse from the quaternion */
- quat_to_mat3(m, vod->viewquat);
+ quat_to_mat3(m, vod->curr.viewquat);
invert_m3_m3(m_inv, m);
/* avoid gimble lock */
@@ -702,30 +785,30 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y)
/* This can likely be computed directly from the quaternion. */
/* Perform the up/down rotation */
- axis_angle_to_quat(quat_local_x, xaxis, sensitivity * -(y - vod->oldy));
- mul_qt_qtqt(quat_local_x, vod->viewquat, quat_local_x);
+ axis_angle_to_quat(quat_local_x, xaxis, sensitivity * -(event_xy[1] - vod->prev.event_xy[1]));
+ mul_qt_qtqt(quat_local_x, vod->curr.viewquat, quat_local_x);
/* Perform the orbital rotation */
- axis_angle_to_quat_single(quat_global_z, 'Z', sensitivity * vod->reverse * (x - vod->oldx));
- mul_qt_qtqt(vod->viewquat, quat_local_x, quat_global_z);
+ axis_angle_to_quat_single(quat_global_z, 'Z', sensitivity * vod->reverse * (event_xy[0] - vod->prev.event_xy[0]));
+ mul_qt_qtqt(vod->curr.viewquat, quat_local_x, quat_global_z);
- viewrotate_apply_dyn_ofs(vod, vod->viewquat);
+ viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat);
}
/* avoid precision loss over time */
- normalize_qt(vod->viewquat);
+ normalize_qt(vod->curr.viewquat);
/* use a working copy so view rotation locking doesnt overwrite the locked
* rotation back into the view we calculate with */
- copy_qt_qt(rv3d->viewquat, vod->viewquat);
+ copy_qt_qt(rv3d->viewquat, vod->curr.viewquat);
/* check for view snap,
* note: don't apply snap to vod->viewquat so the view wont jam up */
if (vod->axis_snap) {
viewrotate_apply_snap(vod);
}
- vod->oldx = x;
- vod->oldy = y;
+ vod->prev.event_xy[0] = event_xy[0];
+ vod->prev.event_xy[1] = event_xy[1];
ED_view3d_camera_lock_sync(vod->v3d, rv3d);
@@ -766,12 +849,12 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
}
- else if (event->type == vod->origkey && event->val == KM_RELEASE) {
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
if (event_code == VIEW_APPLY) {
- viewrotate_apply(vod, event->x, event->y);
+ viewrotate_apply(vod, &event->x);
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
use_autokey = true;
}
@@ -797,6 +880,8 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+
/* makes op->customdata */
viewops_data_alloc(C, op);
vod = op->customdata;
@@ -809,29 +894,33 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
- viewops_data_create(C, op, event, true);
+ viewops_data_create(
+ C, op, event,
+ viewops_flag_from_prefs() |
+ VIEWOPS_FLAG_PERSP_ENSURE |
+ (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
if (ELEM(event->type, MOUSEPAN, MOUSEROTATE)) {
/* Rotate direction we keep always same */
- int x, y;
+ int event_xy[2];
if (event->type == MOUSEPAN) {
if (U.uiflag2 & USER_TRACKPAD_NATURAL) {
- x = 2 * event->x - event->prevx;
- y = 2 * event->y - event->prevy;
+ event_xy[0] = 2 * event->x - event->prevx;
+ event_xy[1] = 2 * event->y - event->prevy;
}
else {
- x = event->prevx;
- y = event->prevy;
+ event_xy[0] = event->prevx;
+ event_xy[1] = event->prevy;
}
}
else {
/* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
- x = event->prevx;
- y = event->y;
+ event_xy[0] = event->prevx;
+ event_xy[1] = event->y;
}
- viewrotate_apply(vod, x, y);
+ viewrotate_apply(vod, event_xy);
ED_view3d_depth_tag_update(vod->rv3d);
viewops_data_free(C, op);
@@ -894,6 +983,8 @@ void VIEW3D_OT_rotate(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
+
+ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_MOUSE_INIT);
}
/** \} */
@@ -1062,7 +1153,6 @@ static void view3d_ndof_orbit(
axis_angle_to_quat_single(quat, 'Z', angle);
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
-
}
else {
float quat[4];
@@ -1213,7 +1303,6 @@ void view3d_ndof_fly(
static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
-
if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
}
@@ -1225,9 +1314,9 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const wmNDOFMotionData *ndof = event->customdata;
viewops_data_alloc(C, op);
- viewops_data_create_ex(
+ viewops_data_create(
C, op, event,
- false, viewops_orbit_mode_ex((U.uiflag & USER_ORBIT_SELECTION) != 0, false));
+ viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0, false));
vod = op->customdata;
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
@@ -1282,7 +1371,6 @@ void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
-
if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
}
@@ -1294,9 +1382,9 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
const wmNDOFMotionData *ndof = event->customdata;
viewops_data_alloc(C, op);
- viewops_data_create_ex(
+ viewops_data_create(
C, op, event,
- false, viewops_orbit_mode_ex((U.uiflag & USER_ORBIT_SELECTION) != 0, false));
+ viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0, false));
vod = op->customdata;
@@ -1487,7 +1575,7 @@ void viewmove_modal_keymap(wmKeyConfig *keyconf)
{
static const EnumPropertyItem modal_items[] = {
{VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
-
+
{VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"},
{VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
@@ -1511,7 +1599,7 @@ void viewmove_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
#endif
-
+
/* assign map to operators */
WM_modalkeymap_assign(keymap, "VIEW3D_OT_move");
}
@@ -1520,13 +1608,13 @@ void viewmove_modal_keymap(wmKeyConfig *keyconf)
static void viewmove_apply(ViewOpsData *vod, int x, int y)
{
if (ED_view3d_offset_lock_check(vod->v3d, vod->rv3d)) {
- vod->rv3d->ofs_lock[0] -= ((vod->oldx - x) * 2.0f) / (float)vod->ar->winx;
- vod->rv3d->ofs_lock[1] -= ((vod->oldy - y) * 2.0f) / (float)vod->ar->winy;
+ vod->rv3d->ofs_lock[0] -= ((vod->prev.event_xy[0] - x) * 2.0f) / (float)vod->ar->winx;
+ vod->rv3d->ofs_lock[1] -= ((vod->prev.event_xy[1] - y) * 2.0f) / (float)vod->ar->winy;
}
else if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) {
const float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f;
- vod->rv3d->camdx += (vod->oldx - x) / (vod->ar->winx * zoomfac);
- vod->rv3d->camdy += (vod->oldy - y) / (vod->ar->winy * zoomfac);
+ vod->rv3d->camdx += (vod->prev.event_xy[0] - x) / (vod->ar->winx * zoomfac);
+ vod->rv3d->camdy += (vod->prev.event_xy[1] - y) / (vod->ar->winy * zoomfac);
CLAMP(vod->rv3d->camdx, -1.0f, 1.0f);
CLAMP(vod->rv3d->camdy, -1.0f, 1.0f);
}
@@ -1534,9 +1622,9 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
float dvec[3];
float mval_f[2];
- mval_f[0] = x - vod->oldx;
- mval_f[1] = y - vod->oldy;
- ED_view3d_win_to_delta(vod->ar, mval_f, dvec, vod->zfac);
+ mval_f[0] = x - vod->prev.event_xy[0];
+ mval_f[1] = y - vod->prev.event_xy[1];
+ ED_view3d_win_to_delta(vod->ar, mval_f, dvec, vod->init.zfac);
add_v3_v3(vod->rv3d->ofs, dvec);
@@ -1545,8 +1633,8 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
}
}
- vod->oldx = x;
- vod->oldy = y;
+ vod->prev.event_xy[0] = x;
+ vod->prev.event_xy[1] = y;
ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
@@ -1581,7 +1669,7 @@ static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
}
- else if (event->type == vod->origkey && event->val == KM_RELEASE) {
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
@@ -1612,9 +1700,14 @@ static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+
/* makes op->customdata */
viewops_data_alloc(C, op);
- viewops_data_create(C, op, event, false);
+ viewops_data_create(
+ C, op, event,
+ viewops_flag_from_prefs() |
+ (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
vod = op->customdata;
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
@@ -1623,9 +1716,9 @@ static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* invert it, trackpad scroll follows same principle as 2d windows this way */
viewmove_apply(vod, 2 * event->x - event->prevx, 2 * event->y - event->prevy);
ED_view3d_depth_tag_update(vod->rv3d);
-
+
viewops_data_free(C, op);
-
+
return OPERATOR_FINISHED;
}
else {
@@ -1657,6 +1750,9 @@ void VIEW3D_OT_move(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
+
+ /* properties */
+ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_MOUSE_INIT);
}
/** \} */
@@ -1671,7 +1767,7 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf)
{
static const EnumPropertyItem modal_items[] = {
{VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
-
+
{VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
{VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
@@ -1695,14 +1791,17 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
#endif
-
+
/* assign map to operators */
WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom");
}
-static void view_zoom_mouseloc_camera(
+/**
+ * \param zoom_xy: Optionally zoom to window location (coords compatible w/ #wmEvent.x, y). Use when not NULL.
+ */
+static void view_zoom_to_window_xy_camera(
Scene *scene, const Depsgraph *depsgraph, View3D *v3d,
- ARegion *ar, float dfac, int mx, int my)
+ ARegion *ar, float dfac, const int zoom_xy[2])
{
RegionView3D *rv3d = ar->regiondata;
const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
@@ -1710,12 +1809,12 @@ static void view_zoom_mouseloc_camera(
const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new);
- if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+ if (zoom_xy != NULL) {
float zoomfac_px;
rctf camera_frame_old;
rctf camera_frame_new;
- const float pt_src[2] = {mx, my};
+ const float pt_src[2] = {zoom_xy[0], zoom_xy[1]};
float pt_dst[2];
float delta_px[2];
@@ -1746,12 +1845,15 @@ static void view_zoom_mouseloc_camera(
}
}
-static void view_zoom_mouseloc_3d(ARegion *ar, float dfac, int mx, int my)
+/**
+ * \param zoom_xy: Optionally zoom to window location (coords compatible w/ #wmEvent.x, y). Use when not NULL.
+ */
+static void view_zoom_to_window_xy_3d(ARegion *ar, float dfac, const int zoom_xy[2])
{
RegionView3D *rv3d = ar->regiondata;
const float dist_new = rv3d->dist * dfac;
- if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+ if (zoom_xy != NULL) {
float dvec[3];
float tvec[3];
float tpos[3];
@@ -1761,8 +1863,8 @@ static void view_zoom_mouseloc_3d(ARegion *ar, float dfac, int mx, int my)
negate_v3_v3(tpos, rv3d->ofs);
- mval_f[0] = (float)(((mx - ar->winrct.xmin) * 2) - ar->winx) / 2.0f;
- mval_f[1] = (float)(((my - ar->winrct.ymin) * 2) - ar->winy) / 2.0f;
+ mval_f[0] = (float)(((zoom_xy[0] - ar->winrct.xmin) * 2) - ar->winx) / 2.0f;
+ mval_f[1] = (float)(((zoom_xy[1] - ar->winrct.ymin) * 2) - ar->winy) / 2.0f;
/* Project cursor position into 3D space */
zfac = ED_view3d_calc_zfac(rv3d, tpos, NULL);
@@ -1788,7 +1890,7 @@ static float viewzoom_scale_value(
const rcti *winrct,
const short viewzoom,
const bool zoom_invert, const bool zoom_invert_force,
- const int xy[2], const int xy_orig[2],
+ const int xy_curr[2], const int xy_init[2],
const float val, const float val_orig,
double *r_timer_lastdraw)
{
@@ -1800,10 +1902,10 @@ static float viewzoom_scale_value(
float fac;
if (U.uiflag & USER_ZOOM_HORIZ) {
- fac = (float)(xy_orig[0] - xy[0]);
+ fac = (float)(xy_init[0] - xy_curr[0]);
}
else {
- fac = (float)(xy_orig[1] - xy[1]);
+ fac = (float)(xy_init[1] - xy_curr[1]);
}
if (zoom_invert != zoom_invert_force) {
@@ -1821,8 +1923,8 @@ static float viewzoom_scale_value(
BLI_rcti_cent_x(winrct),
BLI_rcti_cent_y(winrct),
};
- float len_new = 5 + len_v2v2_int(ctr, xy);
- float len_old = 5 + len_v2v2_int(ctr, xy_orig);
+ float len_new = 5 + len_v2v2_int(ctr, xy_curr);
+ float len_old = 5 + len_v2v2_int(ctr, xy_init);
/* intentionally ignore 'zoom_invert' for scale */
if (zoom_invert_force) {
@@ -1836,12 +1938,12 @@ static float viewzoom_scale_value(
float len_old = 5;
if (U.uiflag & USER_ZOOM_HORIZ) {
- len_new += (winrct->xmax - xy[0]);
- len_old += (winrct->xmax - xy_orig[0]);
+ len_new += (winrct->xmax - (xy_curr[0]));
+ len_old += (winrct->xmax - (xy_init[0]));
}
else {
- len_new += (winrct->ymax - xy[1]);
- len_old += (winrct->ymax - xy_orig[1]);
+ len_new += (winrct->ymax - (xy_curr[1]));
+ len_old += (winrct->ymax - (xy_init[1]));
}
if (zoom_invert != zoom_invert_force) {
@@ -1855,25 +1957,48 @@ static float viewzoom_scale_value(
return zfac;
}
+static float viewzoom_scale_value_offset(
+ const rcti *winrct,
+ const short viewzoom,
+ const bool zoom_invert, const bool zoom_invert_force,
+ const int xy_curr[2], const int xy_init[2], const int xy_offset[2],
+ const float val, const float val_orig,
+ double *r_timer_lastdraw)
+{
+ const int xy_curr_offset[2] = {
+ xy_curr[0] + xy_offset[0],
+ xy_curr[1] + xy_offset[1],
+ };
+ const int xy_init_offset[2] = {
+ xy_init[0] + xy_offset[0],
+ xy_init[1] + xy_offset[1],
+ };
+ return viewzoom_scale_value(
+ winrct, viewzoom, zoom_invert, zoom_invert_force,
+ xy_curr_offset, xy_init_offset,
+ val, val_orig, r_timer_lastdraw);
+}
+
static void viewzoom_apply_camera(
ViewOpsData *vod, const int xy[2],
- const short viewzoom, const bool zoom_invert)
+ const short viewzoom, const bool zoom_invert, const bool zoom_to_pos)
{
float zfac;
- float zoomfac_prev = BKE_screen_view3d_zoom_to_fac(vod->camzoom_prev) * 2.0f;
+ float zoomfac_prev = BKE_screen_view3d_zoom_to_fac(vod->init.camzoom) * 2.0f;
float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f;
- zfac = viewzoom_scale_value(
- &vod->ar->winrct, viewzoom, zoom_invert, true, xy, &vod->origx,
+ zfac = viewzoom_scale_value_offset(
+ &vod->ar->winrct, viewzoom, zoom_invert, true,
+ xy, vod->init.event_xy, vod->init.event_xy_offset,
zoomfac, zoomfac_prev,
- &vod->timer_lastdraw);
+ &vod->prev.time);
if (zfac != 1.0f && zfac != 0.0f) {
/* calculate inverted, then invert again (needed because of camera zoom scaling) */
zfac = 1.0f / zfac;
- view_zoom_mouseloc_camera(
+ view_zoom_to_window_xy_camera(
vod->scene, vod->depsgraph, vod->v3d,
- vod->ar, zfac, vod->oldx, vod->oldy);
+ vod->ar, zfac, zoom_to_pos ? vod->prev.event_xy : NULL);
}
ED_region_tag_redraw(vod->ar);
@@ -1881,25 +2006,26 @@ static void viewzoom_apply_camera(
static void viewzoom_apply_3d(
ViewOpsData *vod, const int xy[2],
- const short viewzoom, const bool zoom_invert)
+ const short viewzoom, const bool zoom_invert, const bool zoom_to_pos)
{
float zfac;
float dist_range[2];
ED_view3d_dist_range_get(vod->v3d, dist_range);
- zfac = viewzoom_scale_value(
- &vod->ar->winrct, viewzoom, zoom_invert, false, xy, &vod->origx,
- vod->rv3d->dist, vod->dist_prev,
- &vod->timer_lastdraw);
+ zfac = viewzoom_scale_value_offset(
+ &vod->ar->winrct, viewzoom, zoom_invert, false,
+ xy, vod->init.event_xy, vod->init.event_xy_offset,
+ vod->rv3d->dist, vod->init.dist,
+ &vod->prev.time);
if (zfac != 1.0f) {
const float zfac_min = dist_range[0] / vod->rv3d->dist;
const float zfac_max = dist_range[1] / vod->rv3d->dist;
CLAMP(zfac, zfac_min, zfac_max);
- view_zoom_mouseloc_3d(
- vod->ar, zfac, vod->oldx, vod->oldy);
+ view_zoom_to_window_xy_3d(
+ vod->ar, zfac, zoom_to_pos ? vod->prev.event_xy : NULL);
}
/* these limits were in old code too */
@@ -1916,15 +2042,15 @@ static void viewzoom_apply_3d(
static void viewzoom_apply(
ViewOpsData *vod, const int xy[2],
- const short viewzoom, const bool zoom_invert)
+ const short viewzoom, const bool zoom_invert, const bool zoom_to_pos)
{
if ((vod->rv3d->persp == RV3D_CAMOB) &&
(vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0)
{
- viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert);
+ viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert, zoom_to_pos);
}
else {
- viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert);
+ viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert, zoom_to_pos);
}
}
@@ -1958,12 +2084,16 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
}
- else if (event->type == vod->origkey && event->val == KM_RELEASE) {
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
if (event_code == VIEW_APPLY) {
- viewzoom_apply(vod, &event->x, U.viewzoom, (U.uiflag & USER_ZOOM_INVERT) != 0);
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+ viewzoom_apply(
+ vod, &event->x, U.viewzoom,
+ (U.uiflag & USER_ZOOM_INVERT) != 0,
+ (use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
use_autokey = true;
}
@@ -1997,7 +2127,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
float dist_range[2];
const int delta = RNA_int_get(op->ptr, "delta");
- int mx, my;
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
if (op->customdata) {
ViewOpsData *vod = op->customdata;
@@ -2013,33 +2143,39 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
v3d = sa->spacedata.first;
rv3d = ar->regiondata;
- mx = RNA_struct_property_is_set(op->ptr, "mx") ? RNA_int_get(op->ptr, "mx") : ar->winx / 2;
- my = RNA_struct_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") : ar->winy / 2;
use_cam_zoom = (rv3d->persp == RV3D_CAMOB) && !(rv3d->is_persp && ED_view3d_camera_lock_check(v3d, rv3d));
+ int zoom_xy_buf[2];
+ const int *zoom_xy = NULL;
+ if (use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
+ zoom_xy_buf[0] = RNA_struct_property_is_set(op->ptr, "mx") ? RNA_int_get(op->ptr, "mx") : ar->winx / 2;
+ zoom_xy_buf[1] = RNA_struct_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") : ar->winy / 2;
+ zoom_xy = zoom_xy_buf;
+ }
+
ED_view3d_dist_range_get(v3d, dist_range);
if (delta < 0) {
const float step = 1.2f;
/* this min and max is also in viewmove() */
if (use_cam_zoom) {
- view_zoom_mouseloc_camera(scene, depsgraph, v3d, ar, step, mx, my);
+ view_zoom_to_window_xy_camera(scene, depsgraph, v3d, ar, step, zoom_xy);
}
else {
if (rv3d->dist < dist_range[1]) {
- view_zoom_mouseloc_3d(ar, step, mx, my);
+ view_zoom_to_window_xy_3d(ar, step, zoom_xy);
}
}
}
else {
const float step = 1.0f / 1.2f;
if (use_cam_zoom) {
- view_zoom_mouseloc_camera(scene, depsgraph, v3d, ar, step, mx, my);
+ view_zoom_to_window_xy_camera(scene, depsgraph, v3d, ar, step, zoom_xy);
}
else {
if (rv3d->dist > dist_range[0]) {
- view_zoom_mouseloc_3d(ar, step, mx, my);
+ view_zoom_to_window_xy_3d(ar, step, zoom_xy);
}
}
}
@@ -2065,9 +2201,14 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+
/* makes op->customdata */
viewops_data_alloc(C, op);
- viewops_data_create(C, op, event, false);
+ viewops_data_create(
+ C, op, event,
+ viewops_flag_from_prefs() |
+ (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
vod = op->customdata;
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
@@ -2085,14 +2226,16 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
if (U.uiflag & USER_ZOOM_HORIZ) {
- vod->origx = vod->oldx = event->x;
- viewzoom_apply(vod, &event->prevx, USER_ZOOM_DOLLY, (U.uiflag & USER_ZOOM_INVERT) != 0);
+ vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x;
}
else {
/* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
- vod->origy = vod->oldy = vod->origy + event->x - event->prevx;
- viewzoom_apply(vod, &event->prevx, USER_ZOOM_DOLLY, (U.uiflag & USER_ZOOM_INVERT) != 0);
+ vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->x - event->prevx;
}
+ viewzoom_apply(
+ vod, &event->prevx, USER_ZOOM_DOLLY,
+ (U.uiflag & USER_ZOOM_INVERT) != 0,
+ (use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
ED_view3d_depth_tag_update(vod->rv3d);
@@ -2104,7 +2247,7 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (U.viewzoom == USER_ZOOM_CONT) {
/* needs a timer to continue redrawing */
vod->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
- vod->timer_lastdraw = PIL_check_seconds_timer();
+ vod->prev.time = PIL_check_seconds_timer();
}
/* add temp handler */
@@ -2123,8 +2266,6 @@ static void viewzoom_cancel(bContext *C, wmOperator *op)
void VIEW3D_OT_zoom(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
ot->name = "Zoom View";
ot->description = "Zoom in/out in the view";
@@ -2140,11 +2281,10 @@ void VIEW3D_OT_zoom(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
- RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
- prop = RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- prop = RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Zoom Position Y", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ /* properties */
+ view3d_operator_properties_common(
+ ot,
+ V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT);
}
/** \} */
@@ -2186,7 +2326,7 @@ void viewdolly_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
#endif
-
+
/* assign map to operators */
WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly");
}
@@ -2204,13 +2344,13 @@ static bool viewdolly_offset_lock_check(bContext *C, wmOperator *op)
}
}
-static void view_dolly_mouseloc(ARegion *ar, float orig_ofs[3], float dvec[3], float dfac)
+static void view_dolly_to_vector_3d(ARegion *ar, float orig_ofs[3], float dvec[3], float dfac)
{
RegionView3D *rv3d = ar->regiondata;
madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, -(1.0f - dfac));
}
-static void viewdolly_apply(ViewOpsData *vod, int x, int y, const short zoom_invert)
+static void viewdolly_apply(ViewOpsData *vod, const int xy[2], const short zoom_invert)
{
float zfac = 1.0;
@@ -2218,21 +2358,23 @@ static void viewdolly_apply(ViewOpsData *vod, int x, int y, const short zoom_inv
float len1, len2;
if (U.uiflag & USER_ZOOM_HORIZ) {
- len1 = (vod->ar->winrct.xmax - x) + 5;
- len2 = (vod->ar->winrct.xmax - vod->origx) + 5;
+ len1 = (vod->ar->winrct.xmax - xy[0]) + 5;
+ len2 = (vod->ar->winrct.xmax - vod->init.event_xy[0]) + 5;
}
else {
- len1 = (vod->ar->winrct.ymax - y) + 5;
- len2 = (vod->ar->winrct.ymax - vod->origy) + 5;
+ len1 = (vod->ar->winrct.ymax - xy[1]) + 5;
+ len2 = (vod->ar->winrct.ymax - vod->init.event_xy[1]) + 5;
}
- if (zoom_invert)
+ if (zoom_invert) {
SWAP(float, len1, len2);
+ }
zfac = 1.0f + ((len1 - len2) * 0.01f * vod->rv3d->dist);
}
- if (zfac != 1.0f)
- view_dolly_mouseloc(vod->ar, vod->ofs, vod->mousevec, zfac);
+ if (zfac != 1.0f) {
+ view_dolly_to_vector_3d(vod->ar, vod->init.ofs, vod->init.mousevec, zfac);
+ }
if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_sync(vod->sa, vod->ar);
@@ -2270,12 +2412,12 @@ static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
}
- else if (event->type == vod->origkey && event->val == KM_RELEASE) {
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
if (event_code == VIEW_APPLY) {
- viewdolly_apply(vod, event->x, event->y, (U.uiflag & USER_ZOOM_INVERT) != 0);
+ viewdolly_apply(vod, &event->x, (U.uiflag & USER_ZOOM_INVERT) != 0);
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
use_autokey = true;
}
@@ -2312,7 +2454,7 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
sa = vod->sa;
ar = vod->ar;
- copy_v3_v3(mousevec, vod->mousevec);
+ copy_v3_v3(mousevec, vod->init.mousevec);
}
else {
sa = CTX_wm_area(C);
@@ -2324,17 +2466,14 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
v3d = sa->spacedata.first;
rv3d = ar->regiondata;
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+
/* overwrite the mouse vector with the view direction (zoom into the center) */
- if ((U.uiflag & USER_ZOOM_TO_MOUSEPOS) == 0) {
+ if ((use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) {
normalize_v3_v3(mousevec, rv3d->viewinv[2]);
}
- if (delta < 0) {
- view_dolly_mouseloc(ar, rv3d->ofs, mousevec, 0.2f);
- }
- else {
- view_dolly_mouseloc(ar, rv3d->ofs, mousevec, 1.8f);
- }
+ view_dolly_to_vector_3d(ar, rv3d->ofs, mousevec, delta < 0 ? 0.2f : 1.8f);
if (rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_sync(sa, ar);
@@ -2384,7 +2523,12 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ED_region_tag_redraw(vod->ar);
}
- viewops_data_create(C, op, event, false);
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+
+ viewops_data_create(
+ C, op, event,
+ viewops_flag_from_prefs() |
+ (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
/* if one or the other zoom position aren't set, set from event */
@@ -2398,24 +2542,22 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
else {
/* overwrite the mouse vector with the view direction (zoom into the center) */
- if ((U.uiflag & USER_ZOOM_TO_MOUSEPOS) == 0) {
- negate_v3_v3(vod->mousevec, vod->rv3d->viewinv[2]);
- normalize_v3(vod->mousevec);
+ if ((use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) {
+ negate_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]);
+ normalize_v3(vod->init.mousevec);
}
if (event->type == MOUSEZOOM) {
/* Bypass Zoom invert flag for track pads (pass false always) */
if (U.uiflag & USER_ZOOM_HORIZ) {
- vod->origx = vod->oldx = event->x;
- viewdolly_apply(vod, event->prevx, event->prevy, (U.uiflag & USER_ZOOM_INVERT) == 0);
+ vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x;
}
else {
-
/* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
- vod->origy = vod->oldy = vod->origy + event->x - event->prevx;
- viewdolly_apply(vod, event->prevx, event->prevy, (U.uiflag & USER_ZOOM_INVERT) == 0);
+ vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->x - event->prevx;
}
+ viewdolly_apply(vod, &event->prevx, (U.uiflag & USER_ZOOM_INVERT) == 0);
ED_view3d_depth_tag_update(vod->rv3d);
viewops_data_free(C, op);
@@ -2453,9 +2595,9 @@ void VIEW3D_OT_dolly(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
- RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX);
- RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Zoom Position Y", "", 0, INT_MAX);
+ /* properties */
+ view3d_operator_properties_common(
+ ot, V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT);
}
/** \} */
@@ -2465,9 +2607,11 @@ void VIEW3D_OT_dolly(wmOperatorType *ot)
*
* Move & Zoom the view to fit all of it's contents.
* \{ */
-static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar,
- const float min[3], const float max[3],
- bool ok_dist, const int smooth_viewtx)
+
+static void view3d_from_minmax(
+ bContext *C, View3D *v3d, ARegion *ar,
+ const float min[3], const float max[3],
+ bool ok_dist, const int smooth_viewtx)
{
RegionView3D *rv3d = ar->regiondata;
float afm[3];
@@ -2533,7 +2677,9 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar,
/* smooth view does viewlock RV3D_BOXVIEW copy */
}
-/* same as view3d_from_minmax but for all regions (except cameras) */
+/**
+ * Same as #view3d_from_minmax but for all regions (except cameras).
+ */
static void view3d_from_minmax_multi(
bContext *C, View3D *v3d,
const float min[3], const float max[3],
@@ -2553,7 +2699,7 @@ static void view3d_from_minmax_multi(
}
}
-static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in 2.4x */
+static int view3d_all_exec(bContext *C, wmOperator *op)
{
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -2618,8 +2764,6 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in
void VIEW3D_OT_view_all(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
ot->name = "View All";
ot->description = "View all objects in scene";
@@ -2632,8 +2776,8 @@ void VIEW3D_OT_view_all(wmOperatorType *ot)
/* flags */
ot->flag = 0;
- prop = RNA_def_boolean(ot->srna, "use_all_regions", 0, "All Regions", "View selected for all regions");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS);
RNA_def_boolean(ot->srna, "center", 0, "Center", "");
}
@@ -2682,11 +2826,8 @@ static int viewselected_exec(bContext *C, wmOperator *op)
break;
}
}
- if (base)
- ob = base->object;
}
-
if (is_gp_edit) {
CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
{
@@ -2756,8 +2897,6 @@ static int viewselected_exec(bContext *C, wmOperator *op)
void VIEW3D_OT_view_selected(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
ot->name = "View Selected";
ot->description = "Move the view to the selection center";
@@ -2770,9 +2909,8 @@ void VIEW3D_OT_view_selected(wmOperatorType *ot)
/* flags */
ot->flag = 0;
- /* rna later */
- prop = RNA_def_boolean(ot->srna, "use_all_regions", 0, "All Regions", "View selected for all regions");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS);
}
/** \} */
@@ -2825,7 +2963,6 @@ static int view_lock_to_active_exec(bContext *C, wmOperator *UNUSED(op))
Object *obact = CTX_data_active_object(C);
if (v3d) {
-
ED_view3d_lock_clear(v3d);
v3d->ob_centre = obact; /* can be NULL */
@@ -2881,7 +3018,7 @@ static int viewcenter_cursor_exec(bContext *C, wmOperator *op)
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
Scene *scene = CTX_data_scene(C);
-
+
if (rv3d) {
ARegion *ar = CTX_wm_region(C);
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
@@ -2897,7 +3034,7 @@ static int viewcenter_cursor_exec(bContext *C, wmOperator *op)
/* smooth view does viewlock RV3D_BOXVIEW copy */
}
-
+
return OPERATOR_FINISHED;
}
@@ -2907,11 +3044,11 @@ void VIEW3D_OT_view_center_cursor(wmOperatorType *ot)
ot->name = "Center View to Cursor";
ot->description = "Center the view so that the cursor is in the middle of the view";
ot->idname = "VIEW3D_OT_view_center_cursor";
-
+
/* api callbacks */
ot->exec = viewcenter_cursor_exec;
ot->poll = ED_operator_view3d_active;
-
+
/* flags */
ot->flag = 0;
}
@@ -3131,7 +3268,6 @@ static int render_border_exec(bContext *C, wmOperator *op)
}
return OPERATOR_FINISHED;
-
}
void VIEW3D_OT_render_border(wmOperatorType *ot)
@@ -3154,7 +3290,7 @@ void VIEW3D_OT_render_border(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* rna */
+ /* properties */
WM_operator_properties_border(ot);
prop = RNA_def_boolean(ot->srna, "camera_only", false, "Camera Only",
@@ -3195,7 +3331,6 @@ static int clear_render_border_exec(bContext *C, wmOperator *UNUSED(op))
border->ymax = 1.0f;
return OPERATOR_FINISHED;
-
}
void VIEW3D_OT_clear_render_border(wmOperatorType *ot)
@@ -3238,7 +3373,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
/* ZBuffer depth vars */
float depth_close = FLT_MAX;
- float p[3];
+ float cent[2], p[3];
/* note; otherwise opengl won't work */
view3d_operator_needs_opengl(C);
@@ -3255,22 +3390,22 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
/* Get Z Depths, needed for perspective, nice for ortho */
ED_view3d_draw_depth(&eval_ctx, CTX_data_depsgraph(C), ar, v3d, true);
-
+
{
/* avoid allocating the whole depth buffer */
ViewDepths depth_temp = {0};
/* avoid view3d_update_depths() for speed. */
view3d_update_depths_rect(ar, &depth_temp, &rect);
-
+
/* find the closest Z pixel */
depth_close = view3d_depth_near(&depth_temp);
-
+
MEM_SAFE_FREE(depth_temp.depths);
}
- float centx = (((float)rect.xmin) + ((float)rect.xmax)) / 2;
- float centy = (((float)rect.ymin) + ((float)rect.ymax)) / 2;
+ cent[0] = (((float)rect.xmin) + ((float)rect.xmax)) / 2;
+ cent[1] = (((float)rect.ymin) + ((float)rect.ymax)) / 2;
if (rv3d->is_persp) {
float p_corner[3];
@@ -3281,7 +3416,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
/* convert border to 3d coordinates */
- if ((!ED_view3d_unproject(ar, centx, centy, depth_close, p)) ||
+ if ((!ED_view3d_unproject(ar, cent[0], cent[1], depth_close, p)) ||
(!ED_view3d_unproject(ar, rect.xmin, rect.ymin, depth_close, p_corner)))
{
return OPERATOR_CANCELLED;
@@ -3303,7 +3438,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
new_dist = rv3d->dist;
/* convert the drawn rectangle into 3d space */
- if (depth_close != FLT_MAX && ED_view3d_unproject(ar, centx, centy, depth_close, p)) {
+ if (depth_close != FLT_MAX && ED_view3d_unproject(ar, cent[0], cent[1], depth_close, p)) {
negate_v3_v3(new_ofs, p);
}
else {
@@ -3382,7 +3517,7 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot)
/* flags */
ot->flag = 0;
- /* rna */
+ /* properties */
WM_operator_properties_gesture_border_zoom(ot);
}
@@ -3399,7 +3534,7 @@ static void view3d_set_1_to_1_viewborder(Scene *scene, const Depsgraph *depsgrap
RegionView3D *rv3d = ar->regiondata;
float size[2];
int im_width = (scene->r.size * scene->r.xsch) / 100;
-
+
ED_view3d_calc_camera_border_size(scene, depsgraph, ar, v3d, rv3d, size);
rv3d->camzoom = BKE_screen_view3d_zoom_from_fac((float)im_width / size[0]);
@@ -3642,7 +3777,6 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
&(const V3D_SmoothParams) {
.camera = v3d->camera, .ofs = rv3d->ofs, .quat = rv3d->viewquat,
.dist = &rv3d->dist, .lens = &v3d->lens});
-
}
else {
/* return to settings of last view */
@@ -3687,6 +3821,8 @@ void VIEW3D_OT_viewnumpad(wmOperatorType *ot)
/* -------------------------------------------------------------------- */
/** \name View Orbit Operator
+ *
+ * Rotate (orbit) in incremental steps. For interactive orbit see #VIEW3D_OT_rotate.
* \{ */
static const EnumPropertyItem prop_view_orbit_items[] = {
@@ -3803,7 +3939,7 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot)
/* flags */
ot->flag = 0;
-
+
/* properties */
prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX);
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
@@ -3842,15 +3978,15 @@ static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y))
tot = vod->ar->winrct.xmax - vod->ar->winrct.xmin;
len1 = (vod->ar->winrct.xmax - x) / tot;
- len2 = (vod->ar->winrct.xmax - vod->origx) / tot;
+ len2 = (vod->ar->winrct.xmax - vod->init.event_xy[0]) / tot;
angle = (len1 - len2) * (float)M_PI * 4.0f;
}
if (angle != 0.0f)
- view_roll_angle(vod->ar, vod->rv3d->viewquat, vod->oldquat, vod->mousevec, angle);
+ view_roll_angle(vod->ar, vod->rv3d->viewquat, vod->init.quat, vod->init.mousevec, angle);
if (vod->use_dyn_ofs) {
- view3d_orbit_apply_dyn_ofs(vod->rv3d->ofs, vod->ofs, vod->oldquat, vod->rv3d->viewquat, vod->dyn_ofs);
+ view3d_orbit_apply_dyn_ofs(vod->rv3d->ofs, vod->init.ofs, vod->init.quat, vod->rv3d->viewquat, vod->dyn_ofs);
}
if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
@@ -3888,7 +4024,7 @@ static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
}
- else if (event->type == vod->origkey && event->val == KM_RELEASE) {
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
@@ -3992,17 +4128,17 @@ static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
else {
/* makes op->customdata */
viewops_data_alloc(C, op);
- viewops_data_create(C, op, event, false);
+ viewops_data_create(C, op, event, viewops_flag_from_prefs());
vod = op->customdata;
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
/* overwrite the mouse vector with the view direction */
- normalize_v3_v3(vod->mousevec, vod->rv3d->viewinv[2]);
- negate_v3(vod->mousevec);
+ normalize_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]);
+ negate_v3(vod->init.mousevec);
if (event->type == MOUSEROTATE) {
- vod->origx = vod->oldx = event->x;
+ vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x;
viewroll_apply(vod, event->prevx, event->prevy);
ED_view3d_depth_tag_update(vod->rv3d);
@@ -4063,7 +4199,7 @@ static const EnumPropertyItem prop_view_pan_items[] = {
/* -------------------------------------------------------------------- */
/** \name View Pan Operator
*
- * Move (pan) in incremental steps.
+ * Move (pan) in incremental steps. For interactive pan see #VIEW3D_OT_move.
* \{ */
static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -4077,10 +4213,10 @@ static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
else if (pandir == V3D_VIEW_PANDOWN) { y = 25; }
viewops_data_alloc(C, op);
- viewops_data_create(C, op, event, false);
+ viewops_data_create(C, op, event, viewops_flag_from_prefs());
ViewOpsData *vod = op->customdata;
- viewmove_apply(vod, vod->oldx + x, vod->oldy + y);
+ viewmove_apply(vod, vod->prev.event_xy[0] + x, vod->prev.event_xy[1] + y);
ED_view3d_depth_tag_update(vod->rv3d);
viewops_data_free(C, op);
@@ -4101,7 +4237,7 @@ void VIEW3D_OT_view_pan(wmOperatorType *ot)
/* flags */
ot->flag = 0;
-
+
/* Properties */
ot->prop = RNA_def_enum(ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction of View Pan");
}
@@ -4130,7 +4266,6 @@ static int viewpersportho_exec(bContext *C, wmOperator *UNUSED(op))
}
return OPERATOR_FINISHED;
-
}
void VIEW3D_OT_view_persportho(wmOperatorType *ot)
@@ -4210,7 +4345,7 @@ static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEven
Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
Image *ima;
CameraBGImage *bgpic;
-
+
ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
/* may be NULL, continue anyway */
@@ -4240,7 +4375,7 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_UNDO;
-
+
/* properties */
RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Image name to assign");
WM_operator_properties_filesel(
@@ -4271,13 +4406,11 @@ static int background_image_remove_exec(bContext *C, wmOperator *op)
BKE_camera_background_image_remove(cam, bgpic_rem);
WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
-
return OPERATOR_FINISHED;
}
else {
return OPERATOR_CANCELLED;
}
-
}
void VIEW3D_OT_background_image_remove(wmOperatorType *ot)
@@ -4293,7 +4426,7 @@ void VIEW3D_OT_background_image_remove(wmOperatorType *ot)
/* flags */
ot->flag = 0;
-
+
/* properties */
RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Background image index to remove", 0, INT_MAX);
}
@@ -4361,7 +4494,6 @@ static int view3d_clipping_invoke(bContext *C, wmOperator *op, const wmEvent *ev
}
}
-/* toggles */
void VIEW3D_OT_clip_border(wmOperatorType *ot)
{
@@ -4381,7 +4513,7 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot)
/* flags */
ot->flag = 0;
- /* rna */
+ /* properties */
WM_operator_properties_border(ot);
}
@@ -4400,14 +4532,14 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
RegionView3D *rv3d = ar->regiondata;
bool flip;
bool depth_used = false;
-
+
/* normally the caller should ensure this,
* but this is called from areas that aren't already dealing with the viewport */
if (rv3d == NULL)
return;
ED_view3d_calc_zfac(rv3d, fp, &flip);
-
+
/* reset the depth based on the view offset (we _know_ the offset is infront of us) */
if (flip) {
negate_v3_v3(fp, rv3d->ofs);
@@ -4415,7 +4547,7 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
ED_view3d_calc_zfac(rv3d, fp, NULL /* &flip */ );
}
- if (U.uiflag & USER_ZBUF_CURSOR) { /* maybe this should be accessed some other way */
+ if (U.uiflag & USER_DEPTH_CURSOR) { /* maybe this should be accessed some other way */
EvaluationContext eval_ctx;
struct Depsgraph *graph = CTX_data_depsgraph(C);
@@ -4496,9 +4628,6 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot)
/* flags */
// ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* rna later */
-
}
/** \} */
@@ -4512,14 +4641,14 @@ static int enable_manipulator_invoke(bContext *C, wmOperator *op, const wmEvent
View3D *v3d = CTX_wm_view3d(C);
v3d->twtype = 0;
-
+
if (RNA_boolean_get(op->ptr, "translate"))
v3d->twtype |= V3D_MANIP_TRANSLATE;
if (RNA_boolean_get(op->ptr, "rotate"))
v3d->twtype |= V3D_MANIP_ROTATE;
if (RNA_boolean_get(op->ptr, "scale"))
v3d->twtype |= V3D_MANIP_SCALE;
-
+
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
return OPERATOR_FINISHED;
@@ -4533,12 +4662,12 @@ void VIEW3D_OT_enable_manipulator(wmOperatorType *ot)
ot->name = "Enable 3D Manipulator";
ot->description = "Enable the transform manipulator for use";
ot->idname = "VIEW3D_OT_enable_manipulator";
-
+
/* api callbacks */
ot->invoke = enable_manipulator_invoke;
ot->poll = ED_operator_view3d_active;
-
- /* rna later */
+
+ /* properties */
prop = RNA_def_boolean(ot->srna, "translate", 0, "Translate", "Enable the translate manipulator");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna, "rotate", 0, "Rotate", "Enable the rotate manipulator");
@@ -4563,7 +4692,7 @@ static int toggle_render_exec(bContext *C, wmOperator *UNUSED(op))
v3d->prev_drawtype = v3d->drawtype;
v3d->drawtype = OB_RENDER;
}
- ED_view3d_shade_update(CTX_data_main(C), CTX_data_scene(C), v3d, CTX_wm_area(C));
+ ED_view3d_shade_update(CTX_data_main(C), v3d, CTX_wm_area(C));
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index a1dc2a21477..3ed6c87b750 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -55,7 +55,7 @@
#include "WM_types.h"
#include "ED_mesh.h"
-#include "ED_util.h"
+#include "ED_undo.h"
#include "ED_screen.h"
#include "UI_interface.h"
@@ -95,14 +95,14 @@ static void handle_view3d_lock(bContext *C)
* - uiTemplateLayers in interface/ code for buttons
* - ED_view3d_view_layer_set for RNA
*/
-static void view3d_layers_editmode_ensure(Scene *scene, View3D *v3d)
+static void view3d_layers_editmode_ensure(View3D *v3d, Object *obedit)
{
/* sanity check - when in editmode disallow switching the editmode layer off since its confusing
* an alternative would be to always draw the editmode object. */
- if (scene->obedit && (scene->obedit->lay & v3d->lay) == 0) {
+ if (obedit && (obedit->lay & v3d->lay) == 0) {
int bit;
for (bit = 0; bit < 32; bit++) {
- if (scene->obedit->lay & (1u << bit)) {
+ if (obedit->lay & (1u << bit)) {
v3d->lay |= (1u << bit);
break;
}
@@ -112,9 +112,9 @@ static void view3d_layers_editmode_ensure(Scene *scene, View3D *v3d)
static int view3d_layers_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;
+ Object *obedit = CTX_data_edit_object(C);
int nr = RNA_int_get(op->ptr, "nr");
const bool toggle = RNA_boolean_get(op->ptr, "toggle");
@@ -130,7 +130,7 @@ static int view3d_layers_exec(bContext *C, wmOperator *op)
/* return to active layer only */
v3d->lay = v3d->lay_prev;
- view3d_layers_editmode_ensure(scene, v3d);
+ view3d_layers_editmode_ensure(v3d, obedit);
}
else {
v3d->lay_prev = v3d->lay;
@@ -151,7 +151,7 @@ static int view3d_layers_exec(bContext *C, wmOperator *op)
v3d->lay = (1 << nr);
}
- view3d_layers_editmode_ensure(scene, v3d);
+ view3d_layers_editmode_ensure(v3d, obedit);
/* set active layer, ensure to always have one */
if (v3d->lay & (1 << nr))
@@ -288,8 +288,10 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
bGPdata *gpd = CTX_data_gpencil_data(C);
uiBlock *block;
uiLayout *row;
- bool is_paint = ob && !(gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) &&
- ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT);
+ bool is_paint = (
+ ob && !(gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) &&
+ ELEM(ob->mode,
+ OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT));
RNA_pointer_create(&screen->id, &RNA_SpaceView3D, v3d, &v3dptr);
RNA_pointer_create(&scene->id, &RNA_ToolSettings, ts, &toolsptr);
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 5e34bc188f0..0f56f1265bc 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -160,7 +160,7 @@ bool draw_glsl_material(Scene *scene, struct ViewLayer *view_layer, struct Objec
void draw_object_instance(const struct EvaluationContext *eval_ctx, Scene *scene, struct ViewLayer *view_layer, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline, const float wire_col[4]);
void draw_object_backbufsel(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob);
-void draw_object_wire_color(Scene *scene, struct ViewLayer *, Base *base, unsigned char r_ob_wire_col[4]);
+void draw_object_wire_color(struct ViewLayer *, Base *base, unsigned char r_ob_wire_col[4]);
void drawaxes(const float viewmat_local[4][4], float size, char drawtype, const unsigned char color[4]);
void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
const char dt, const short dflag, const unsigned char ob_wire_col[4],
@@ -368,8 +368,8 @@ extern bool view3d_camera_border_hack_test;
/* temporary for legacy viewport to work */
void VP_legacy_drawcursor(Scene *scene, struct ViewLayer *view_layer, ARegion *ar, View3D *v3d);
-void VP_legacy_draw_view_axis(RegionView3D *rv3d, rcti *rect);
-void VP_legacy_draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect);
+void VP_legacy_draw_view_axis(RegionView3D *rv3d, const rcti *rect);
+void VP_legacy_draw_viewport_name(ARegion *ar, View3D *v3d, const rcti *rect);
void VP_legacy_draw_selected_name(Scene *scene, struct Object *ob, rcti *rect);
void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit);
void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth);
@@ -377,7 +377,7 @@ void VP_legacy_view3d_main_region_setup_view(const struct EvaluationContext *eva
bool VP_legacy_view3d_stereo3d_active(struct wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d);
void VP_legacy_view3d_stereo3d_setup(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar);
void draw_dupli_objects(const struct EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d, Base *base);
-bool VP_legacy_use_depth(Scene *scene, View3D *v3d);
+bool VP_legacy_use_depth(View3D *v3d, struct Object *obedit);
void VP_drawviewborder(Scene *scene, const struct Depsgraph *depsgraph, ARegion *ar, View3D *v3d);
void VP_drawrenderborder(ARegion *ar, View3D *v3d);
void VP_view3d_draw_background_none(void);
@@ -391,6 +391,6 @@ void VP_deprecated_view3d_draw_objects(
const struct EvaluationContext *eval_ctx,
Scene *scene, View3D *v3d, ARegion *ar,
const char **grid_unit,
- const bool do_bgpic, const bool draw_offscreen, struct GPUFX *fx);
+ const bool do_bgpic, const bool draw_offscreen);
#endif /* __VIEW3D_INTERN_H__ */
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_camera.c b/source/blender/editors/space_view3d/view3d_manipulator_camera.c
index 6a45ec5095f..3c826c69f3c 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_camera.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_camera.c
@@ -64,8 +64,14 @@ struct CameraWidgetGroup {
static bool WIDGETGROUP_camera_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
{
Object *ob = CTX_data_active_object(C);
-
- return (ob && ob->type == OB_CAMERA);
+ if (ob && ob->type == OB_CAMERA) {
+ Camera *camera = ob->data;
+ /* TODO: support overrides. */
+ if (camera->id.lib == NULL) {
+ return true;
+ }
+ }
+ return false;
}
static void WIDGETGROUP_camera_setup(const bContext *C, wmManipulatorGroup *mgroup)
@@ -332,10 +338,7 @@ static void manipulator_render_border_prop_matrix_set(
static bool WIDGETGROUP_camera_view_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
{
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
/* This is just so the border isn't always in the way,
* stealing mouse clicks from regular usage.
@@ -347,9 +350,15 @@ static bool WIDGETGROUP_camera_view_poll(const bContext *C, wmManipulatorGroupTy
}
}
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ View3D *v3d = CTX_wm_view3d(C);
if (rv3d->persp == RV3D_CAMOB) {
if (scene->r.mode & R_BORDER) {
- return true;
+ /* TODO: support overrides. */
+ if (scene->id.lib == NULL) {
+ return true;
+ }
}
}
else if (v3d->flag2 & V3D_RENDER_BORDER) {
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c
index 6a34f493caf..e76be448be4 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c
@@ -31,7 +31,7 @@
#include "BKE_object.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "ED_screen.h"
#include "ED_manipulator_library.h"
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
index 9f655fff8a1..6a5d63b180f 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
@@ -231,6 +231,16 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmManipulatorG
}
}
+ /* Modal operators, don't use initial mouse location since we're clicking on a button. */
+ {
+ int mpr_ids[] = {MPR_MOVE, MPR_ROTATE, MPR_ZOOM};
+ for (int i = 0; i < ARRAY_SIZE(mpr_ids); i++) {
+ wmManipulator *mpr = navgroup->mpr_array[mpr_ids[i]];
+ wmManipulatorOpElem *mpop = WM_manipulator_operator_get(mpr, 0);
+ RNA_boolean_set(&mpop->ptr, "use_mouse_init", false);
+ }
+ }
+
{
wmManipulator *mpr = navgroup->mpr_array[MPR_ROTATE];
mpr->scale_basis = MANIPULATOR_SIZE / 2;
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
index 424b5dae402..c3f8d92ed7f 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
@@ -131,7 +131,7 @@ static void axis_geom_draw(
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
glBlendFunc(GL_ONE, GL_ZERO);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
index e8d540bcc9d..f9955f29774 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
@@ -277,7 +277,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
}
else if (state == RULER_STATE_DRAG) {
ruler_info->snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), CTX_data_engine_type(C), 0,
+ CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), 0,
ruler_info->ar, CTX_wm_view3d(C));
}
else {
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 79fa9e14dc1..8e6f5228b09 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -82,7 +82,7 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
for (Group *group = bmain->group.first; group; group = group->id.next) {
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
if (object && (object->id.tag & LIB_TAG_DOIT)) {
BKE_copybuffer_tag_ID(&group->id);
@@ -91,7 +91,7 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
break;
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index 093425fc3bc..f61aad2806e 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -282,7 +282,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
}
else if (state == RULER_STATE_DRAG) {
ruler_info->snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), CTX_data_engine_type(C), 0,
+ CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), 0,
ruler_info->ar, CTX_wm_view3d(C));
}
else {
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index f51aad34c29..21219bced3c 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -49,7 +49,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
-#include "BLI_lasso.h"
+#include "BLI_lasso_2d.h"
#include "BLI_rect.h"
#include "BLI_linklist.h"
#include "BLI_listbase.h"
@@ -85,6 +85,7 @@
#include "ED_armature.h"
#include "ED_curve.h"
+#include "ED_lattice.h"
#include "ED_particle.h"
#include "ED_mesh.h"
#include "ED_object.h"
@@ -109,7 +110,7 @@ float ED_view3d_select_dist_px(void)
}
/* TODO: should return whether there is valid context to continue */
-void view3d_set_viewcontext(bContext *C, ViewContext *vc)
+void ED_view3d_viewcontext_init(bContext *C, ViewContext *vc)
{
memset(vc, 0, sizeof(ViewContext));
vc->ar = CTX_wm_region(C);
@@ -226,9 +227,10 @@ typedef struct LassoSelectUserData {
bool is_changed;
} LassoSelectUserData;
-static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data,
- ViewContext *vc, const rcti *rect, const int (*mcords)[2],
- const int moves, const bool select)
+static void view3d_userdata_lassoselect_init(
+ LassoSelectUserData *r_data,
+ ViewContext *vc, const rcti *rect, const int (*mcords)[2],
+ const int moves, const bool select)
{
r_data->vc = vc;
@@ -303,7 +305,8 @@ static bool edge_inside_rect(const rctf *rect, const float v1[2], const float v2
return 1;
}
-static void do_lasso_select_pose__doSelectBone(void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2])
+static void do_lasso_select_pose__doSelectBone(
+ void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2])
{
LassoSelectUserData *data = userData;
bArmature *arm = data->vc->obact->data;
@@ -390,8 +393,9 @@ static void object_deselect_all_visible(ViewLayer *view_layer)
}
}
-static void do_lasso_select_objects(ViewContext *vc, const int mcords[][2], const short moves,
- const bool extend, const bool select)
+static void do_lasso_select_objects(
+ ViewContext *vc, const int mcords[][2], const short moves,
+ const bool extend, const bool select)
{
Base *base;
@@ -423,7 +427,8 @@ static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, cons
BM_vert_select_set(data->vc->em->bm, eve, data->select);
}
}
-static void do_lasso_select_mesh__doSelectEdge(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
+static void do_lasso_select_mesh__doSelectEdge(
+ void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
{
LassoSelectUserData *data = userData;
@@ -846,9 +851,10 @@ static void do_lasso_select_node(int mcords[][2], short moves, const bool select
}
#endif
-static void view3d_lasso_select(bContext *C, ViewContext *vc,
- const int mcords[][2], short moves,
- bool extend, bool select)
+static void view3d_lasso_select(
+ bContext *C, ViewContext *vc,
+ const int mcords[][2], short moves,
+ bool extend, bool select)
{
Object *ob = CTX_data_active_object(C);
@@ -917,7 +923,7 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
view3d_operator_needs_opengl(C);
/* setup view context for argument to callbacks */
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
extend = RNA_boolean_get(op->ptr, "extend");
select = !RNA_boolean_get(op->ptr, "deselect");
@@ -949,61 +955,8 @@ void VIEW3D_OT_select_lasso(wmOperatorType *ot)
WM_operator_properties_gesture_lasso_select(ot);
}
-
-/* ************************************************* */
-
-#if 0
-/* smart function to sample a rect spiralling outside, nice for backbuf selection */
-static unsigned int samplerect(unsigned int *buf, int size, unsigned int dontdo)
-{
- Base *base;
- unsigned int *bufmin, *bufmax;
- int a, b, rc, tel, len, dirvec[4][2], maxob;
- unsigned int retval = 0;
-
- base = LASTBASE;
- if (base == 0) return 0;
- maxob = base->object->select_color;
-
- len = (size - 1) / 2;
- rc = 0;
-
- dirvec[0][0] = 1;
- dirvec[0][1] = 0;
- dirvec[1][0] = 0;
- dirvec[1][1] = -size;
- dirvec[2][0] = -1;
- dirvec[2][1] = 0;
- dirvec[3][0] = 0;
- dirvec[3][1] = size;
-
- bufmin = buf;
- bufmax = buf + size * size;
- buf += len * size + len;
-
- for (tel = 1; tel <= size; tel++) {
-
- for (a = 0; a < 2; a++) {
- for (b = 0; b < tel; b++) {
-
- if (*buf && *buf <= maxob && *buf != dontdo) return *buf;
- if (*buf == dontdo) retval = dontdo; /* if only color dontdo is available, still return dontdo */
-
- buf += (dirvec[rc][0] + dirvec[rc][1]);
-
- if (buf < bufmin || buf >= bufmax) return retval;
- }
- rc++;
- rc &= 3;
- }
- }
- return retval;
-}
-#endif
-
/* ************************** mouse select ************************* */
-
/* The max number of menu items in an object select menu */
typedef struct SelMenuItemF {
char idname[MAX_ID_NAME - 2];
@@ -1014,7 +967,8 @@ typedef struct SelMenuItemF {
static SelMenuItemF object_mouse_select_menu_data[SEL_MENU_SIZE];
/* special (crappy) operator only for menu select */
-static const EnumPropertyItem *object_select_menu_enum_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *object_select_menu_enum_itemf(
+ bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
{
EnumPropertyItem *item = NULL, item_tmp = {0};
int totitem = 0;
@@ -1199,7 +1153,7 @@ static Base *object_mouse_select_menu(
}
}
-static bool selectbuffer_has_bones(const unsigned int *buffer, const unsigned int hits)
+static bool selectbuffer_has_bones(const uint *buffer, const uint hits)
{
unsigned int i;
for (i = 0; i < hits; i++) {
@@ -1320,8 +1274,9 @@ finally:
}
/* returns basact */
-static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int hits,
- Base *startbase, bool has_bones, bool do_nearest)
+static Base *mouse_select_eval_buffer(
+ ViewContext *vc, const uint *buffer, int hits,
+ Base *startbase, bool has_bones, bool do_nearest)
{
ViewLayer *view_layer = vc->view_layer;
Base *base, *basact = NULL;
@@ -1417,7 +1372,7 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
view3d_operator_needs_opengl(C);
CTX_data_eval_ctx(C, &eval_ctx);
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
hits = mixed_bones_object_selectbuffer(&eval_ctx, &vc, buffer, mval, false, false, &do_nearest);
@@ -1468,7 +1423,7 @@ static bool ed_object_select_pick(
/* setup view context for argument to callbacks */
CTX_data_eval_ctx(C, &eval_ctx);
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
is_obedit = (vc.obedit != NULL);
if (object) {
@@ -1493,8 +1448,9 @@ static bool ed_object_select_pick(
while (base) {
if (BASE_SELECTABLE(base)) {
float screen_co[2];
- if (ED_view3d_project_float_global(ar, base->object->obmat[3], screen_co,
- V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
+ if (ED_view3d_project_float_global(
+ ar, base->object->obmat[3], screen_co,
+ V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
{
float dist_temp = len_manhattan_v2v2(mval_fl, screen_co);
if (base == BASACT(view_layer)) dist_temp += 10.0f;
@@ -1593,7 +1549,7 @@ static bool ed_object_select_pick(
}
}
}
- else if (ED_do_pose_selectbuffer(scene, view_layer, basact, buffer, hits, extend, deselect, toggle, do_nearest)) {
+ else if (ED_do_pose_selectbuffer(view_layer, basact, buffer, hits, extend, deselect, toggle, do_nearest)) {
/* then bone is found */
/* we make the armature selected:
@@ -1680,8 +1636,9 @@ typedef struct BoxSelectUserData {
bool is_changed;
} BoxSelectUserData;
-static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data,
- ViewContext *vc, const rcti *rect, const bool select)
+static void view3d_userdata_boxselect_init(
+ BoxSelectUserData *r_data,
+ ViewContext *vc, const rcti *rect, const bool select)
{
r_data->vc = vc;
@@ -1795,7 +1752,8 @@ static int do_paintvert_box_select(
return OPERATOR_FINISHED;
}
-static void do_nurbs_box_select__doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
+static void do_nurbs_box_select__doSelect(
+ void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
{
BoxSelectUserData *data = userData;
Object *obedit = data->vc->obedit;
@@ -1914,7 +1872,8 @@ static void do_mesh_box_select__doSelectVert(void *userData, BMVert *eve, const
BM_vert_select_set(data->vc->em->bm, eve, data->select);
}
}
-static void do_mesh_box_select__doSelectEdge(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
+static void do_mesh_box_select__doSelectEdge(
+ void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
{
BoxSelectUserData *data = userData;
@@ -2131,8 +2090,8 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
EvaluationContext eval_ctx;
Bone *bone;
Object *ob = vc->obact;
- unsigned int *vbuffer = NULL; /* selection buffer */
- unsigned int *col; /* color in buffer */
+ unsigned int *vbuffer = NULL; /* selection buffer */
+ unsigned int *col; /* color in buffer */
int bone_only;
int bone_selected = 0;
int totobj = MAXPICKBUF; /* XXX solve later */
@@ -2180,7 +2139,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
qsort(vbuffer, hits, sizeof(uint[4]), opengl_select_buffer_cmp);
/*
- * Even though 'DRW_draw_select_loop' uses 'DEG_OBJECT_ITER',
+ * Even though 'DRW_draw_select_loop' uses 'DEG_OBJECT_ITER_BEGIN',
* we can be sure the order remains the same between both.
*/
for (base = vc->view_layer->object_bases.first; base && hits; base = base->next) {
@@ -2248,7 +2207,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
/* setup view context for argument to callbacks */
CTX_data_eval_ctx(C, &eval_ctx);
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
select = !RNA_boolean_get(op->ptr, "deselect");
extend = RNA_boolean_get(op->ptr, "extend");
@@ -2513,8 +2472,9 @@ typedef struct CircleSelectUserData {
bool is_changed;
} CircleSelectUserData;
-static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data,
- ViewContext *vc, const bool select, const int mval[2], const float rad)
+static void view3d_userdata_circleselect_init(
+ CircleSelectUserData *r_data,
+ ViewContext *vc, const bool select, const int mval[2], const float rad)
{
r_data->vc = vc;
r_data->select = select;
@@ -2537,7 +2497,8 @@ static void mesh_circle_doSelectVert(void *userData, BMVert *eve, const float sc
BM_vert_select_set(data->vc->em->bm, eve, data->select);
}
}
-static void mesh_circle_doSelectEdge(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index))
+static void mesh_circle_doSelectEdge(
+ void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index))
{
CircleSelectUserData *data = userData;
@@ -2655,7 +2616,8 @@ static void paint_vertsel_circle_select(const struct EvaluationContext *eval_ctx
}
-static void nurbscurve_circle_doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
+static void nurbscurve_circle_doSelect(
+ void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
{
CircleSelectUserData *data = userData;
Object *obedit = data->vc->obedit;
@@ -2766,7 +2728,8 @@ static bool pchan_circle_doSelectJoint(void *userData, bPoseChannel *pchan, cons
}
return 0;
}
-static void do_circle_select_pose__doSelectBone(void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2])
+static void do_circle_select_pose__doSelectBone(
+ void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2])
{
CircleSelectUserData *data = userData;
bArmature *arm = data->vc->obact->data;
@@ -2852,7 +2815,8 @@ static bool armature_circle_doSelectJoint(void *userData, EditBone *ebone, const
}
return 0;
}
-static void do_circle_select_armature__doSelectBone(void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2])
+static void do_circle_select_armature__doSelectBone(
+ void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2])
{
CircleSelectUserData *data = userData;
bArmature *arm = data->vc->obedit->data;
@@ -2977,8 +2941,9 @@ static bool object_circle_select(ViewContext *vc, const bool select, const int m
for (base = FIRSTBASE(view_layer); base; base = base->next) {
if (BASE_SELECTABLE(base) && ((base->flag & BASE_SELECTED) != select_flag)) {
float screen_co[2];
- if (ED_view3d_project_float_global(vc->ar, base->object->obmat[3], screen_co,
- V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
+ if (ED_view3d_project_float_global(
+ vc->ar, base->object->obmat[3], screen_co,
+ V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
{
if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) {
ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
@@ -3010,7 +2975,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
view3d_operator_needs_opengl(C);
CTX_data_eval_ctx(C, &eval_ctx);
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
if (CTX_data_edit_object(C)) {
obedit_circle_select(&eval_ctx, &vc, select, mval, (float)radius);
@@ -3034,7 +2999,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
}
else {
ViewContext vc;
- view3d_set_viewcontext(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
if (object_circle_select(&vc, select, mval, (float)radius)) {
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c
index 5e3c783c1b6..dfa64bd2015 100644
--- a/source/blender/editors/space_view3d/view3d_toolbar.c
+++ b/source/blender/editors/space_view3d/view3d_toolbar.c
@@ -55,7 +55,7 @@
#include "RNA_access.h"
#include "ED_screen.h"
-#include "ED_util.h"
+#include "ED_undo.h"
#include "UI_interface.h"
#include "UI_resources.h"
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 7bb3f443ac6..92b3ec19acb 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -161,7 +161,7 @@ void view3d_operator_needs_opengl(const bContext *C)
view3d_region_operator_needs_opengl(win, ar);
}
-void view3d_region_operator_needs_opengl(wmWindow *win, ARegion *ar)
+void view3d_region_operator_needs_opengl(wmWindow *UNUSED(win), ARegion *ar)
{
/* for debugging purpose, context should always be OK */
if ((ar == NULL) || (ar->regiontype != RGN_TYPE_WINDOW)) {
@@ -170,7 +170,7 @@ void view3d_region_operator_needs_opengl(wmWindow *win, ARegion *ar)
else {
RegionView3D *rv3d = ar->regiondata;
- wmSubWindowSet(win, ar->swinid);
+ wmViewport(&ar->winrct); // TODO: bad
gpuLoadProjectionMatrix(rv3d->winmat);
gpuLoadMatrix(rv3d->viewmat);
}
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 0597f2806b3..1a547d07b80 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -861,6 +861,45 @@ void view3d_opengl_select_cache_end(void)
GPU_select_cache_end();
}
+#ifndef WITH_OPENGL_LEGACY
+struct DrawSelectLoopUserData {
+ uint pass;
+ uint hits;
+ uint *buffer;
+ uint buffer_len;
+ const rcti *rect;
+ char gpu_select_mode;
+};
+
+static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data)
+{
+ bool continue_pass = false;
+ struct DrawSelectLoopUserData *data = user_data;
+ if (stage == DRW_SELECT_PASS_PRE) {
+ GPU_select_begin(data->buffer, data->buffer_len, data->rect, data->gpu_select_mode, data->hits);
+ /* always run POST after PRE. */
+ continue_pass = true;
+ }
+ else if (stage == DRW_SELECT_PASS_POST) {
+ int hits = GPU_select_end();
+ if (data->pass == 0) {
+ /* quirk of GPU_select_end, only take hits value from first call. */
+ data->hits = hits;
+ }
+ if (data->gpu_select_mode == GPU_SELECT_NEAREST_FIRST_PASS) {
+ data->gpu_select_mode = GPU_SELECT_NEAREST_SECOND_PASS;
+ continue_pass = (hits > 0);
+ }
+ data->pass += 1;
+ }
+ else {
+ BLI_assert(0);
+ }
+ return continue_pass;
+
+}
+#endif /* WITH_OPENGL_LEGACY */
+
/**
* \warning be sure to account for a negative return value
* This is an error, "Too many objects in select buffer"
@@ -879,7 +918,7 @@ int view3d_opengl_select(
ARegion *ar = vc->ar;
rcti rect;
int hits;
- const bool use_obedit_skip = (scene->obedit != NULL) && (vc->obedit == NULL);
+ const bool use_obedit_skip = (OBEDIT_FROM_VIEW_LAYER(vc->view_layer) != NULL) && (vc->obedit == NULL);
const bool is_pick_select = (U.gpu_select_pick_deph != 0);
const bool do_passes = (
(is_pick_select == false) &&
@@ -931,6 +970,11 @@ int view3d_opengl_select(
goto finally;
}
+#ifndef WITH_OPENGL_LEGACY
+ /* All of the queries need to be perform on the drawing context. */
+ DRW_opengl_context_enable();
+#endif
+
G.f |= G_PICKSEL;
/* Important we use the 'viewmat' and don't re-calculate since
@@ -941,43 +985,44 @@ int view3d_opengl_select(
v3d->zbuf = true;
glEnable(GL_DEPTH_TEST);
}
-
+
if (vc->rv3d->rflag & RV3D_CLIPPING)
ED_view3d_clipping_set(vc->rv3d);
- GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
#ifdef WITH_OPENGL_LEGACY
if (IS_VIEWPORT_LEGACY(vc->v3d)) {
+ GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest);
+ hits = GPU_select_end();
+
+ if (do_passes && (hits > 0)) {
+ GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
+ ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest);
+ GPU_select_end();
+ }
}
else
#else
{
- DRW_draw_select_loop(graph, ar, v3d, use_obedit_skip, use_nearest, &rect);
+ /* We need to call "GPU_select_*" API's inside DRW_draw_select_loop
+ * because the OpenGL context created & destroyed inside this function. */
+ struct DrawSelectLoopUserData drw_select_loop_user_data = {
+ .pass = 0,
+ .hits = 0,
+ .buffer = buffer,
+ .buffer_len = bufsize,
+ .rect = &rect,
+ .gpu_select_mode = gpu_select_mode,
+ };
+ DRW_draw_select_loop(
+ graph, ar, v3d,
+ use_obedit_skip, use_nearest, &rect,
+ drw_select_loop_pass, &drw_select_loop_user_data);
+ hits = drw_select_loop_user_data.hits;
}
#endif /* WITH_OPENGL_LEGACY */
- hits = GPU_select_end();
-
- /* second pass, to get the closest object to camera */
- if (do_passes && (hits > 0)) {
- GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
-
-#ifdef WITH_OPENGL_LEGACY
- if (IS_VIEWPORT_LEGACY(vc->v3d)) {
- ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest);
- }
- else
-#else
- {
- DRW_draw_select_loop(graph, ar, v3d, use_obedit_skip, use_nearest, &rect);
- }
-#endif /* WITH_OPENGL_LEGACY */
-
- GPU_select_end();
- }
-
G.f &= ~G_PICKSEL;
ED_view3d_draw_setup_view(vc->win, eval_ctx, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL);
@@ -989,7 +1034,12 @@ int view3d_opengl_select(
if (vc->rv3d->rflag & RV3D_CLIPPING)
ED_view3d_clipping_disable();
+#ifndef WITH_OPENGL_LEGACY
+ DRW_opengl_context_disable();
+#endif
+
finally:
+
if (hits < 0) printf("Too many objects in select buffer\n"); /* XXX make error message */
UI_Theme_Restore(&theme_state);
@@ -1058,8 +1108,9 @@ static void game_engine_save_state(bContext *C, wmWindow *win)
glPushAttrib(GL_ALL_ATTRIB_BITS);
- if (obact && obact->mode & OB_MODE_TEXTURE_PAINT)
+ if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
GPU_paint_set_mipmap(1);
+ }
queue_back = win->queue;
@@ -1070,9 +1121,9 @@ static void game_engine_restore_state(bContext *C, wmWindow *win)
{
Object *obact = CTX_data_active_object(C);
- if (obact && obact->mode & OB_MODE_TEXTURE_PAINT)
+ if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
GPU_paint_set_mipmap(0);
-
+ }
/* check because closing win can set to NULL */
if (win) {
win->queue = queue_back;
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index e65f9abae27..3bf0e579bb3 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -58,8 +58,6 @@
#include "GPU_immediate.h"
-#include "RE_engine.h"
-
#include "DEG_depsgraph.h"
#include "view3d_intern.h" /* own include */
@@ -254,7 +252,6 @@ typedef struct WalkInfo {
const struct Depsgraph *depsgraph;
Scene *scene;
ViewLayer *view_layer;
- RenderEngineType *engine_type;
wmTimer *timer; /* needed for redraws */
@@ -522,7 +519,6 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->depsgraph = CTX_data_depsgraph(C);
walk->scene = CTX_data_scene(C);
walk->view_layer = CTX_data_view_layer(C);
- walk->engine_type = CTX_data_engine_type(C);
#ifdef NDOF_WALK_DEBUG
puts("\n-- walk begin --");
@@ -611,7 +607,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->rv3d->rflag |= RV3D_NAVIGATING;
walk->snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), walk->scene, walk->view_layer, walk->engine_type, 0,
+ CTX_data_main(C), walk->scene, walk->view_layer, 0,
walk->ar, walk->v3d);
walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 9f7b438e338..3aeb38970d2 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1707,20 +1707,10 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
TransInfo *t = (TransInfo *)customdata;
if (t->helpline != HLP_NONE) {
- float vecrot[3], cent[2];
+ float cent[2];
float mval[3] = { x, y, 0.0f };
- copy_v3_v3(vecrot, t->center);
- if (t->flag & T_EDIT) {
- Object *ob = t->obedit;
- if (ob) mul_m4_v3(ob->obmat, vecrot);
- }
- else if (t->flag & T_POSE) {
- Object *ob = t->poseobj;
- if (ob) mul_m4_v3(ob->obmat, vecrot);
- }
-
- projectFloatViewEx(t, vecrot, cent, V3D_PROJ_TEST_CLIP_ZERO);
+ projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO);
gpuPushMatrix();
@@ -1890,7 +1880,7 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar)
#endif
/* autokey recording icon... */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
xco -= U.widget_unit;
@@ -2624,9 +2614,6 @@ static void constraintTransLim(TransInfo *t, TransData *td)
if (td->con) {
const bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_LOCLIMIT);
const bConstraintTypeInfo *ctiDist = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_DISTLIMIT);
- EvaluationContext eval_ctx;
-
- CTX_data_eval_ctx(t->context, &eval_ctx);
bConstraintOb cob = {NULL};
bConstraint *con;
@@ -2676,7 +2663,7 @@ static void constraintTransLim(TransInfo *t, TransData *td)
}
/* get constraint targets if needed */
- BKE_constraint_targets_for_solving_get(&eval_ctx, con, &cob, &targets, ctime);
+ BKE_constraint_targets_for_solving_get(&t->eval_ctx, con, &cob, &targets, ctime);
/* do constraint */
cti->evaluate_constraint(con, &cob, &targets);
@@ -6883,7 +6870,7 @@ static void drawEdgeSlide(TransInfo *t)
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
gpuPushMatrix();
gpuMultMatrix(t->obedit->obmat);
@@ -7495,7 +7482,7 @@ static void drawVertSlide(TransInfo *t)
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
gpuPushMatrix();
gpuMultMatrix(t->obedit->obmat);
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 8dc3bca7d38..40f6b64b055 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -41,6 +41,8 @@
#include "DNA_listBase.h"
+#include "DEG_depsgraph.h"
+
/* ************************** Types ***************************** */
struct Depsgraph;
@@ -66,6 +68,8 @@ struct EditBone;
struct RenderEngineType;
struct SnapObjectContext;
+#include "DNA_object_enums.h"
+
/* transinfo->redraw */
typedef enum {
TREDRAW_NOTHING = 0,
@@ -465,6 +469,7 @@ typedef struct TransInfo {
bool remove_on_cancel; /* remove elements if operator is canceled */
+ EvaluationContext eval_ctx;
void *view;
struct bContext *context; /* Only valid (non null) during an operator called function. */
struct ScrArea *sa;
@@ -650,7 +655,8 @@ void restoreBones(TransInfo *t);
#define MANIPULATOR_AXIS_LINE_WIDTH 2.0f
-bool gimbal_axis(struct Object *ob, float gmat[3][3]); /* return 0 when no gimbal for selection */
+/* return 0 when no gimbal for selection */
+bool gimbal_axis(struct Object *ob, float gmat[3][3]);
/*********************** TransData Creation and General Handling *********** */
void createTransData(struct bContext *C, TransInfo *t);
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 4e409e7f77f..f612dc0e474 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -999,7 +999,7 @@ static void setNearestAxis3d(TransInfo *t)
* of two 2D points 30 pixels apart (that's the last factor in the formula) after
* projecting them with ED_view3d_win_to_delta and then get the length of that vector.
*/
- zfac = mul_project_m4_v3_zfac(t->persmat, t->center);
+ zfac = mul_project_m4_v3_zfac(t->persmat, t->center_global);
zfac = len_v3(t->persinv[0]) * 2.0f / t->ar->winx * zfac * 30.0f;
for (i = 0; i < 3; i++) {
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 25c1f9eaddc..3a1c60e4a65 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -2124,7 +2124,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
TransDataExtension *tx;
Object *ob = CTX_data_active_object(C);
ParticleEditSettings *pset = PE_settings(t->scene);
- PTCacheEdit *edit = PE_get_current(t->scene, t->view_layer, ob);
+ PTCacheEdit *edit = PE_get_current(t->scene, ob);
ParticleSystem *psys = NULL;
ParticleSystemModifierData *psmd = NULL;
PTCacheEditPoint *point;
@@ -2241,7 +2241,7 @@ void flushTransParticles(TransInfo *t)
Scene *scene = t->scene;
ViewLayer *view_layer = t->view_layer;
Object *ob = OBACT(view_layer);
- PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
ParticleSystem *psys = edit->psys;
ParticleSystemModifierData *psmd = NULL;
PTCacheEditPoint *point;
@@ -2280,9 +2280,7 @@ void flushTransParticles(TransInfo *t)
point->flag |= PEP_EDIT_RECALC;
}
- EvaluationContext eval_ctx;
- CTX_data_eval_ctx(t->context, &eval_ctx);
- PE_update_object(&eval_ctx, scene, view_layer, OBACT(view_layer), 1);
+ PE_update_object(&t->eval_ctx, scene, OBACT(view_layer), 1);
}
/* ********************* mesh ****************** */
@@ -2694,7 +2692,6 @@ static void createTransEditVerts(TransInfo *t)
{
TransData *tob = NULL;
TransDataExtension *tx = NULL;
- EvaluationContext eval_ctx;
BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
Mesh *me = t->obedit->data;
BMesh *bm = em->bm;
@@ -2713,10 +2710,6 @@ static void createTransEditVerts(TransInfo *t)
int island_info_tot;
int *island_vert_map = NULL;
- DEG_evaluation_context_init_from_scene(&eval_ctx,
- t->scene, t->view_layer, t->engine_type,
- DAG_EVAL_VIEWPORT);
-
/* Even for translation this is needed because of island-orientation, see: T51651. */
const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS);
/* Original index of our connected vertex when connected distances are calculated.
@@ -2800,7 +2793,7 @@ static void createTransEditVerts(TransInfo *t)
if (modifiers_isCorrectableDeformed(t->scene, t->obedit)) {
/* check if we can use deform matrices for modifier from the
* start up to stack, they are more accurate than quats */
- totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh(&eval_ctx, t->scene, t->obedit, em, &defmats, &defcos);
+ totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh(&t->eval_ctx, t->scene, t->obedit, em, &defmats, &defcos);
}
/* if we still have more modifiers, also do crazyspace
@@ -2813,7 +2806,7 @@ static void createTransEditVerts(TransInfo *t)
if (totleft > 0)
#endif
{
- mappedcos = BKE_crazyspace_get_mapped_editverts(&eval_ctx, t->scene, t->obedit);
+ mappedcos = BKE_crazyspace_get_mapped_editverts(&t->eval_ctx, t->scene, t->obedit);
quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode);
if (mappedcos)
@@ -3207,7 +3200,7 @@ static void createTransUVs(bContext *C, TransInfo *t)
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BMLoop *l;
- if (!uvedit_face_visible_test(scene, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, t->obedit, ima, efa)) {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
continue;
}
@@ -3735,67 +3728,136 @@ static void posttrans_mask_clean(Mask *mask)
}
}
+/* Time + Average value */
+typedef struct tRetainedKeyframe {
+ struct tRetainedKeyframe *next, *prev;
+ float frame; /* frame to cluster around */
+ float val; /* average value */
+
+ size_t tot_count; /* number of keyframes that have been averaged */
+ size_t del_count; /* number of keyframes of this sort that have been deleted so far */
+} tRetainedKeyframe;
+
/* Called during special_aftertrans_update to make sure selected keyframes replace
* any other keyframes which may reside on that frame (that is not selected).
*/
static void posttrans_fcurve_clean(FCurve *fcu, const bool use_handle)
{
- float *selcache; /* cache for frame numbers of selected frames (fcu->totvert*sizeof(float)) */
- int len, index, i; /* number of frames in cache, item index */
-
- /* allocate memory for the cache */
- // TODO: investigate using BezTriple columns instead?
- if (fcu->totvert == 0 || fcu->bezt == NULL)
+ /* NOTE: We assume that all keys are sorted */
+ ListBase retained_keys = {NULL, NULL};
+ const bool can_average_points = ((fcu->flag & (FCURVE_INT_VALUES | FCURVE_DISCRETE_VALUES)) == 0);
+
+ /* sanity checks */
+ if ((fcu->totvert == 0) || (fcu->bezt == NULL))
return;
- selcache = MEM_callocN(sizeof(float) * fcu->totvert, "FCurveSelFrameNums");
- len = 0;
- index = 0;
-
- /* We do 2 loops, 1 for marking keyframes for deletion, one for deleting
- * as there is no guarantee what order the keyframes are exactly, even though
- * they have been sorted by time.
+
+ /* 1) Identify selected keyframes, and average the values on those
+ * in case there are collisions due to multiple keys getting scaled
+ * to all end up on the same frame
*/
-
- /* Loop 1: find selected keyframes */
- for (i = 0; i < fcu->totvert; i++) {
+ for (int i = 0; i < fcu->totvert; i++) {
BezTriple *bezt = &fcu->bezt[i];
if (BEZT_ISSEL_ANY(bezt)) {
- selcache[index] = bezt->vec[1][0];
- index++;
- len++;
+ bool found = false;
+
+ /* If there's another selected frame here, merge it */
+ for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
+ if (IS_EQT(rk->frame, bezt->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
+ rk->val += bezt->vec[1][1];
+ rk->tot_count++;
+
+ found = true;
+ break;
+ }
+ else if (rk->frame < bezt->vec[1][0]) {
+ /* Terminate early if have passed the supposed insertion point? */
+ break;
+ }
+ }
+
+ /* If nothing found yet, create a new one */
+ if (found == false) {
+ tRetainedKeyframe *rk = MEM_callocN(sizeof(tRetainedKeyframe), "tRetainedKeyframe");
+
+ rk->frame = bezt->vec[1][0];
+ rk->val = bezt->vec[1][1];
+ rk->tot_count = 1;
+
+ BLI_addtail(&retained_keys, rk);
+ }
}
}
-
- /* Loop 2: delete unselected keyframes on the same frames
- * (if any keyframes were found, or the whole curve wasn't affected)
+
+ if (BLI_listbase_is_empty(&retained_keys)) {
+ /* This may happen if none of the points were selected... */
+ if (G.debug & G_DEBUG) {
+ printf("%s: nothing to do for FCurve %p (rna_path = '%s')\n", __func__, fcu, fcu->rna_path);
+ }
+ return;
+ }
+ else {
+ /* Compute the average values for each retained keyframe */
+ for (tRetainedKeyframe *rk = retained_keys.first; rk; rk = rk->next) {
+ rk->val = rk->val / (float)rk->tot_count;
+ }
+ }
+
+ /* 2) Delete all keyframes duplicating the "retained keys" found above
+ * - Most of these will be unselected keyframes
+ * - Some will be selected keyframes though. For those, we only keep the last one
+ * (or else everything is gone), and replace its value with the averaged value.
*/
- if ((len) && (len != fcu->totvert)) {
- for (i = fcu->totvert - 1; i >= 0; i--) {
- BezTriple *bezt = &fcu->bezt[i];
-
- if (BEZT_ISSEL_ANY(bezt) == 0) {
- /* check beztriple should be removed according to cache */
- for (index = 0; index < len; index++) {
- if (IS_EQF(bezt->vec[1][0], selcache[index])) {
+ for (int i = fcu->totvert - 1; i >= 0; i--) {
+ BezTriple *bezt = &fcu->bezt[i];
+
+ /* Is this keyframe a candidate for deletion? */
+ /* TODO: Replace loop with an O(1) lookup instead */
+ for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
+ if (IS_EQT(bezt->vec[1][0], rk->frame, BEZT_BINARYSEARCH_THRESH)) {
+ /* Selected keys are treated with greater care than unselected ones... */
+ if (BEZT_ISSEL_ANY(bezt)) {
+ /* - If this is the last selected key left (based on rk->del_count) ==> UPDATE IT
+ * (or else we wouldn't have any keyframe left here)
+ * - Otherwise, there are still other selected keyframes on this frame
+ * to be merged down still ==> DELETE IT
+ */
+ if (rk->del_count == rk->tot_count - 1) {
+ /* Update keyframe... */
+ if (can_average_points) {
+ /* TODO: update handles too? */
+ bezt->vec[1][1] = rk->val;
+ }
+ }
+ else {
+ /* Delete Keyframe */
delete_fcurve_key(fcu, i, 0);
- break;
}
- else if (bezt->vec[1][0] < selcache[index])
- break;
+
+ /* Update count of how many we've deleted
+ * - It should only matter that we're doing this for all but the last one
+ */
+ rk->del_count++;
}
+ else {
+ /* Always delete - Unselected keys don't matter */
+ delete_fcurve_key(fcu, i, 0);
+ }
+
+ /* Stop the RK search... we've found our match now */
+ break;
}
}
-
- testhandles_fcurve(fcu, use_handle);
}
-
- /* free cache */
- MEM_freeN(selcache);
+
+ /* 3) Recalculate handles */
+ testhandles_fcurve(fcu, use_handle);
+
+ /* cleanup */
+ BLI_freelistN(&retained_keys);
}
-
/* Called by special_aftertrans_update to make sure selected keyframes replace
* any other keyframes which may reside on that frame (that is not selected).
* remake_action_ipos should have already been called
@@ -5639,9 +5701,6 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
Scene *scene = t->scene;
bool constinv;
bool skip_invert = false;
- EvaluationContext eval_ctx;
-
- CTX_data_eval_ctx(t->context, &eval_ctx);
if (t->mode != TFM_DUMMY && ob->rigidbody_object) {
float rot[3][3], scale[3];
@@ -5689,11 +5748,11 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
if (skip_invert == false && constinv == false) {
ob->transflag |= OB_NO_CONSTRAINTS; /* BKE_object_where_is_calc_time checks this */
- BKE_object_where_is_calc(&eval_ctx, t->scene, ob);
+ BKE_object_where_is_calc(&t->eval_ctx, t->scene, ob);
ob->transflag &= ~OB_NO_CONSTRAINTS;
}
else
- BKE_object_where_is_calc(&eval_ctx, t->scene, ob);
+ BKE_object_where_is_calc(&t->eval_ctx, t->scene, ob);
td->ob = ob;
@@ -6334,14 +6393,11 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
* */
void special_aftertrans_update(bContext *C, TransInfo *t)
{
- EvaluationContext eval_ctx;
Object *ob;
// short redrawipo=0, resetslowpar=1;
const bool canceled = (t->state == TRANS_CANCEL);
const bool duplicate = (t->mode == TFM_TIME_DUPLICATE);
- CTX_data_eval_ctx(C, &eval_ctx);
-
/* early out when nothing happened */
if (t->total == 0 || t->mode == TFM_DUMMY)
return;
@@ -6680,7 +6736,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
* we need to update the pose otherwise no updates get called during
* transform and the auto-ik is not applied. see [#26164] */
struct Object *pose_ob = t->poseobj;
- BKE_pose_where_is(&eval_ctx, t->scene, pose_ob);
+ BKE_pose_where_is(&t->eval_ctx, t->scene, pose_ob);
}
/* set BONE_TRANSFORM flags for autokey, manipulator draw might have changed them */
@@ -6725,7 +6781,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
else if ((t->view_layer->basact) &&
(ob = t->view_layer->basact->object) &&
(ob->mode & OB_MODE_PARTICLE_EDIT) &&
- PE_get_current(t->scene, t->view_layer, ob))
+ PE_get_current(t->scene, ob))
{
/* do nothing */
}
@@ -8484,7 +8540,7 @@ void createTransData(bContext *C, TransInfo *t)
}
}
- else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, view_layer, ob))) {
+ else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, ob))) {
createTransParticleVerts(C, t);
t->flag |= T_POINTS;
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 83a8e978b0d..32cd02c59e6 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -280,7 +280,7 @@ static void animrecord_check_state(Scene *scene, ID *id, wmTimer *animtimer)
/* only push down if action is more than 1-2 frames long */
calc_action_range(adt->action, &astart, &aend, 1);
if (aend > astart + 2.0f) {
- NlaStrip *strip = add_nlastrip_to_stack(adt, adt->action);
+ NlaStrip *strip = BKE_nlastack_add_strip(adt, adt->action);
/* clear reference to action now that we've pushed it onto the stack */
id_us_min(&adt->action->id);
@@ -715,9 +715,6 @@ static void recalcData_spaceclip(TransInfo *t)
static void recalcData_objects(TransInfo *t)
{
Base *base = t->view_layer->basact;
- EvaluationContext eval_ctx;
-
- CTX_data_eval_ctx(t->context, &eval_ctx);
if (t->obedit) {
if (ELEM(t->obedit->type, OB_CURVE, OB_SURF)) {
@@ -907,9 +904,11 @@ static void recalcData_objects(TransInfo *t)
BIK_clear_data(ob->pose);
}
else
- BKE_pose_where_is(&eval_ctx, t->scene, ob);
+ BKE_pose_where_is(&t->eval_ctx, t->scene, ob);
}
- else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) && PE_get_current(t->scene, t->view_layer, base->object)) {
+ else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) &&
+ PE_get_current(t->scene, base->object))
+ {
if (t->state != TRANS_CANCEL) {
applyProject(t);
}
@@ -1120,6 +1119,7 @@ static int initTransInfo_edit_pet_to_flag(const int proportional)
*/
void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event)
{
+ CTX_data_eval_ctx(C, &t->eval_ctx);
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *sce = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -1921,14 +1921,6 @@ void calculateCenter(TransInfo *t)
if (t->spacetype == SPACE_VIEW3D) {
/* ED_view3d_calc_zfac() defines a factor for perspective depth correction, used in ED_view3d_win_to_delta() */
- float vec[3];
- if (t->flag & (T_EDIT | T_POSE)) {
- Object *ob = t->obedit ? t->obedit : t->poseobj;
- mul_v3_m4v3(vec, ob->obmat, t->center);
- }
- else {
- copy_v3_v3(vec, t->center);
- }
/* zfac is only used convertViewVec only in cases operator was invoked in RGN_TYPE_WINDOW
* and never used in other cases.
@@ -1937,7 +1929,7 @@ void calculateCenter(TransInfo *t)
* for a region different from RGN_TYPE_WINDOW.
*/
if (t->ar->regiontype == RGN_TYPE_WINDOW) {
- t->zfac = ED_view3d_calc_zfac(t->ar->regiondata, vec, NULL);
+ t->zfac = ED_view3d_calc_zfac(t->ar->regiondata, t->center_global, NULL);
}
else {
t->zfac = 0.0f;
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 0643687c29a..8944817baca 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -63,6 +63,8 @@
#include "BIF_gl.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
#include "WM_message.h"
@@ -973,7 +975,7 @@ static int calc_manipulator_stats(
/* pass */
}
else if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) {
- PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
PTCacheEditPoint *point;
PTCacheEditKey *ek;
int k;
@@ -1065,7 +1067,7 @@ static void manipulator_prepare_mat(
bGPdata *gpd = CTX_data_gpencil_data(C);
Object *ob = OBACT(view_layer);
- if (((v3d->around == V3D_AROUND_ACTIVE) && (scene->obedit == NULL)) &&
+ if (((v3d->around == V3D_AROUND_ACTIVE) && (OBEDIT_FROM_OBACT(ob) == NULL)) &&
((gpd == NULL) || !(gpd->flag & GP_DATA_STROKE_EDITMODE)) &&
(!(ob->mode & OB_MODE_POSE)))
{
diff --git a/source/blender/editors/transform/transform_manipulator2d.c b/source/blender/editors/transform/transform_manipulator2d.c
index 6e2d0d8c5c0..a9414a7f4bf 100644
--- a/source/blender/editors/transform/transform_manipulator2d.c
+++ b/source/blender/editors/transform/transform_manipulator2d.c
@@ -353,6 +353,10 @@ void ED_widgetgroup_manipulator2d_draw_prepare(const bContext *C, wmManipulatorG
*/
bool ED_widgetgroup_manipulator2d_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
{
+ if ((U.manipulator_flag & USER_MANIPULATOR_DRAW) == 0) {
+ return false;
+ }
+
SpaceImage *sima = CTX_wm_space_image(C);
Object *obedit = CTX_data_edit_object(C);
@@ -368,7 +372,7 @@ bool ED_widgetgroup_manipulator2d_poll(const bContext *C, wmManipulatorGroupType
/* check if there's a selected poly */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index ab0e24671eb..d5d25888ec8 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -316,7 +316,8 @@ static void transformops_loopsel_hack(bContext *C, wmOperator *op)
/* still switch if we were originally in face select mode */
if ((ts->selectmode != selectmode_orig) && (selectmode_orig != SCE_SELECT_FACE)) {
- BMEditMesh *em = BKE_editmesh_from_object(scene->obedit);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
em->selectmode = ts->selectmode = selectmode_orig;
EDBM_selectmode_set(em);
}
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index f8b11a0bcae..7b3f91b81da 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -911,7 +911,7 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3
}
else if (is_next_sel) {
/* A segment, add the edge normal */
- sub_v3_v3v3(tvec, bp->vec, bp_next->vec );
+ sub_v3_v3v3(tvec, bp->vec, bp_next->vec);
normalize_v3(tvec);
add_v3_v3(normal, tvec);
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 30aad46843d..5cb3f262ced 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -70,6 +70,8 @@
#include "ED_view3d.h"
#include "ED_transform_snap_object_context.h"
+#include "DEG_depsgraph.h"
+
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -582,8 +584,7 @@ static void initSnappingMode(TransInfo *t)
if (t->spacetype == SPACE_VIEW3D) {
if (t->tsnap.object_context == NULL) {
t->tsnap.object_context = ED_transform_snap_object_context_create_view3d(
- G.main, t->scene, t->view_layer, t->engine_type, 0,
- t->ar, t->view);
+ G.main, t->scene, t->view_layer, 0, t->ar, t->view);
ED_transform_snap_object_context_set_editmesh_callbacks(
t->tsnap.object_context,
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 8f0590eb5b9..2a9b4790eaf 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -62,6 +62,10 @@
#include "transform.h"
+/* -------------------------------------------------------------------- */
+/** Internal Data Types
+ * \{ */
+
enum eViewProj {
VIEW_PROJ_NONE = -1,
VIEW_PROJ_ORTHO = 0,
@@ -137,10 +141,8 @@ struct SnapObjectContext {
/** \} */
-
/* -------------------------------------------------------------------- */
-
-/** Common utilities
+/** Common Utilities
* \{ */
@@ -260,9 +262,7 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt);
/** \} */
-
/* -------------------------------------------------------------------- */
-
/** \name Ray Cast Funcs
* \{ */
@@ -789,7 +789,6 @@ static void raycast_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob,
* Walks through all objects in the scene to find the `hit` on object surface.
*
* \param sctx: Snap context to store data.
- * \param snapdata: struct generated in `set_snapdata`.
* \param snap_select : from enum eSnapSelect.
* \param use_object_edit_cage : Uses the coordinates of BMesh(if any) to do the snapping.
* \param obj_list: List with objects to snap (created in `create_object_list`).
@@ -822,7 +821,7 @@ static bool raycastObjects(
Object **r_ob, float r_obmat[4][4],
ListBase *r_hit_list)
{
- Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL;
+ Object *obedit = use_object_edit_cage ? OBEDIT_FROM_VIEW_LAYER(sctx->eval_ctx.view_layer) : NULL;
struct RaycastObjUserData data = {
.ray_start = ray_start,
@@ -846,9 +845,7 @@ static bool raycastObjects(
/** \} */
-
/* -------------------------------------------------------------------- */
-
/** Snap Nearest utilities
* \{ */
@@ -1158,9 +1155,7 @@ static float dist_squared_to_projected_aabb_simple(
/** \} */
-
/* -------------------------------------------------------------------- */
-
/** Walk DFS
* \{ */
@@ -1256,7 +1251,6 @@ static bool cb_nearest_walk_order(const BVHTreeAxisRange *UNUSED(bounds), char a
/** \} */
/* -------------------------------------------------------------------- */
-
/** \name Internal Object Snapping API
* \{ */
@@ -1358,7 +1352,7 @@ static bool snapArmature(
static bool snapCurve(
SnapData *snapdata,
- Object *ob, Curve *cu, float obmat[4][4],
+ Curve *cu, float obmat[4][4], bool use_obedit,
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
@@ -1376,12 +1370,12 @@ static bool snapCurve(
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
dist_px_sq = SQUARE(*dist_px);
- for (Nurb *nu = (ob->mode == OB_MODE_EDIT ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
+ for (Nurb *nu = (use_obedit ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
for (int u = 0; u < nu->pntsu; u++) {
switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
- if (ob->mode == OB_MODE_EDIT) {
+ if (use_obedit) {
if (nu->bezt) {
/* don't snap to selected (moving) or hidden */
if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) {
@@ -1966,7 +1960,7 @@ static bool snapObject(
else if (ob->type == OB_CURVE) {
retval = snapCurve(
snapdata,
- ob, ob->data, obmat,
+ ob->data, obmat, use_obedit,
ray_depth, dist_px,
r_loc, r_no);
}
@@ -2060,7 +2054,7 @@ static bool snapObjectsRay(
float r_loc[3], float r_no[3],
Object **r_ob, float r_obmat[4][4])
{
- Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL;
+ Object *obedit = use_object_edit_cage ? OBEDIT_FROM_VIEW_LAYER(sctx->eval_ctx.view_layer) : NULL;
struct SnapObjUserData data = {
.snapdata = snapdata,
@@ -2080,14 +2074,12 @@ static bool snapObjectsRay(
/** \} */
-
/* -------------------------------------------------------------------- */
-
/** \name Public Object Snapping API
* \{ */
SnapObjectContext *ED_transform_snap_object_context_create(
- Main *bmain, Scene *scene, ViewLayer *view_layer, RenderEngineType *engine_type, int flag)
+ Main *bmain, Scene *scene, ViewLayer *view_layer, int flag)
{
SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__);
@@ -2096,7 +2088,8 @@ SnapObjectContext *ED_transform_snap_object_context_create(
sctx->bmain = bmain;
sctx->scene = scene;
- DEG_evaluation_context_init_from_scene(&sctx->eval_ctx, scene, view_layer, engine_type, DAG_EVAL_VIEWPORT);
+ DEG_evaluation_context_init_from_scene(
+ &sctx->eval_ctx, scene, view_layer, DAG_EVAL_VIEWPORT);
sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
@@ -2105,11 +2098,11 @@ SnapObjectContext *ED_transform_snap_object_context_create(
}
SnapObjectContext *ED_transform_snap_object_context_create_view3d(
- Main *bmain, Scene *scene, ViewLayer *view_layer, RenderEngineType *engine_type, int flag,
+ Main *bmain, Scene *scene, ViewLayer *view_layer, int flag,
/* extra args for view3d */
const ARegion *ar, const View3D *v3d)
{
- SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, view_layer, engine_type, flag);
+ SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, view_layer, flag);
sctx->use_v3d = true;
sctx->v3d_data.ar = ar;
diff --git a/source/blender/editors/undo/CMakeLists.txt b/source/blender/editors/undo/CMakeLists.txt
new file mode 100644
index 00000000000..89832604ed8
--- /dev/null
+++ b/source/blender/editors/undo/CMakeLists.txt
@@ -0,0 +1,45 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/clog
+)
+
+set(SRC
+ ed_undo.c
+ memfile_undo.c
+ undo_system_types.c
+
+ undo_intern.h
+)
+
+if(WITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
+blender_add_lib(bf_editor_undo "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/undo/ed_undo.c
index 9e28a5f84ec..d8b194e3336 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/undo/ed_undo.c
@@ -25,17 +25,16 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/editors/util/undo.c
- * \ingroup edutil
+/** \file blender/editors/undo/ed_undo.c
+ * \ingroup edundo
*/
-#include <stdlib.h>
#include <string.h>
-#include <math.h>
#include "MEM_guardedalloc.h"
-#include "DNA_object_types.h"
+#include "CLG_log.h"
+
#include "DNA_scene_types.h"
#include "BLI_utildefines.h"
@@ -45,22 +44,14 @@
#include "BKE_blender_undo.h"
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_library_override.h"
#include "BKE_main.h"
#include "BKE_screen.h"
+#include "BKE_undo_system.h"
-#include "ED_armature.h"
-#include "ED_particle.h"
-#include "ED_curve.h"
#include "ED_gpencil.h"
-#include "ED_mball.h"
-#include "ED_mesh.h"
-#include "ED_object.h"
#include "ED_render.h"
#include "ED_screen.h"
-#include "ED_paint.h"
-#include "ED_util.h"
-#include "ED_text.h"
+#include "ED_undo.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -71,63 +62,50 @@
#include "UI_interface.h"
#include "UI_resources.h"
-#include "util_intern.h"
+/** We only need this locally. */
+static CLG_LogRef LOG = {"ed.undo"};
-/* ***************** generic undo system ********************* */
+/* -------------------------------------------------------------------- */
+/** \name Generic Undo System Access
+ *
+ * Non-operator undo editor functions.
+ * \{ */
void ED_undo_push(bContext *C, const char *str)
{
- Object *obedit = CTX_data_edit_object(C);
- Object *obact = CTX_data_active_object(C);
-
- if (G.debug & G_DEBUG)
- printf("%s: %s\n", __func__, str);
-
- /* Always do it for now, this might need to be refined... */
- BKE_main_override_static_operations_create(CTX_data_main(C));
-
- if (obedit) {
- if (U.undosteps == 0) return;
-
- if (obedit->type == OB_MESH)
- undo_push_mesh(C, str);
- else if (ELEM(obedit->type, OB_CURVE, OB_SURF))
- undo_push_curve(C, str);
- else if (obedit->type == OB_FONT)
- undo_push_font(C, str);
- else if (obedit->type == OB_MBALL)
- undo_push_mball(C, str);
- else if (obedit->type == OB_LATTICE)
- undo_push_lattice(C, str);
- else if (obedit->type == OB_ARMATURE)
- undo_push_armature(C, str);
- }
- else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
- if (U.undosteps == 0) return;
+ CLOG_INFO(&LOG, 1, "name='%s'", str);
+
+ const int steps = U.undosteps;
- PE_undo_push(CTX_data_scene(C), CTX_data_view_layer(C), str);
+ if (steps <= 0) {
+ return;
}
- else if (obact && obact->mode & OB_MODE_SCULPT) {
- /* do nothing for now */
+
+ wmWindowManager *wm = CTX_wm_manager(C);
+
+ /* Only apply limit if this is the last undo step. */
+ if (wm->undo_stack->step_active && (wm->undo_stack->step_active->next == NULL)) {
+ BKE_undosys_stack_limit_steps_and_memory(wm->undo_stack, steps - 1, 0);
}
- else {
- BKE_undo_write(C, str);
+
+ BKE_undosys_step_push(wm->undo_stack, C, str);
+
+ if (U.undomemory != 0) {
+ const size_t memory_limit = (size_t)U.undomemory * 1024 * 1024;
+ BKE_undosys_stack_limit_steps_and_memory(wm->undo_stack, 0, memory_limit);
}
- WM_file_tag_modified(C);
+ WM_file_tag_modified();
}
/* note: also check undo_history_exec() in bottom if you change notifiers */
static int ed_undo_step(bContext *C, int step, const char *undoname)
{
+ CLOG_INFO(&LOG, 1, "name='%s', step=%d", undoname, step);
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
- Main *bmain = CTX_data_main(C);
+ // Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *obedit = CTX_data_edit_object(C);
- Object *obact = CTX_data_active_object(C);
- ScrArea *sa = CTX_wm_area(C);
/* undo during jobs are running can easily lead to freeing data using by jobs,
* or they can just lead to freezing job in some other cases */
@@ -135,100 +113,45 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
return OPERATOR_CANCELLED;
}
+ /* TODO(campbell): undo_system: use undo system */
/* grease pencil can be can be used in plenty of spaces, so check it first */
if (ED_gpencil_session_active()) {
return ED_undo_gpencil_step(C, step, undoname);
}
- if (sa && (sa->spacetype == SPACE_IMAGE)) {
- SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
-
- if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) || (sima->mode == SI_MODE_PAINT)) {
- if (!ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname) && undoname) {
- if (U.uiflag & USER_GLOBALUNDO) {
- ED_viewport_render_kill_jobs(wm, bmain, true);
- BKE_undo_name(C, undoname);
- }
- }
-
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- return OPERATOR_FINISHED;
- }
- }
-
- if (sa && (sa->spacetype == SPACE_TEXT)) {
- ED_text_undo_step(C, step);
- }
- else if (obedit) {
- if (OB_TYPE_SUPPORT_EDITMODE(obedit->type)) {
- if (undoname)
- undo_editmode_name(C, undoname);
- else
- undo_editmode_step(C, step);
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
- }
- }
- else {
- /* Note: we used to do a fall-through here where if the
- * mode-specific undo system had no more steps to undo (or
- * redo), the global undo would run.
- *
- * That was inconsistent with editmode, and also makes for
- * unecessarily tricky interaction with the other undo
- * systems. */
- if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
- ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname);
+ /* Undo System */
+ {
+ if (undoname) {
+ UndoStep *step_data = BKE_undosys_step_find_by_name(wm->undo_stack, undoname);
+ BKE_undosys_step_undo_with_data(wm->undo_stack, C, step_data);
}
- else if (obact && obact->mode & OB_MODE_SCULPT) {
- ED_undo_paint_step(C, UNDO_PAINT_MESH, step, undoname);
- }
- else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
- if (step == 1)
- PE_undo(scene, view_layer);
- else
- PE_redo(scene, view_layer);
- }
- else if (U.uiflag & USER_GLOBALUNDO) {
- // note python defines not valid here anymore.
- //#ifdef WITH_PYTHON
- // XXX BPY_scripts_clear_pyobjects();
- //#endif
-
- /* for global undo/redo we should just clear the editmode stack */
- /* for example, texface stores image pointers */
- undo_editmode_clear();
-
- ED_viewport_render_kill_jobs(wm, bmain, true);
-
- if (undoname)
- BKE_undo_name(C, undoname);
- else
- BKE_undo_step(C, step);
-
- scene = CTX_data_scene(C);
-
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
+ else {
+ BKE_undosys_step_undo_compat_only(wm->undo_stack, C, step);
}
}
-
+
WM_event_add_notifier(C, NC_WINDOW, NULL);
WM_event_add_notifier(C, NC_WM | ND_UNDO, NULL);
if (win) {
win->addmousemove = true;
}
-
+
return OPERATOR_FINISHED;
}
void ED_undo_grouped_push(bContext *C, const char *str)
{
/* do nothing if previous undo task is the same as this one (or from the same undo group) */
- const char *last_undo = BKE_undo_get_name_last();
+ {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ if (wm->undo_stack->steps.last) {
+ const UndoStep *us = wm->undo_stack->steps.last;
+ if (STREQ(str, us->name)) {
+ return;
+ }
+ }
- if (last_undo && STREQ(str, last_undo)) {
- return;
}
/* push as usual */
@@ -269,49 +192,29 @@ void ED_undo_pop_op(bContext *C, wmOperator *op)
/* name optionally, function used to check for operator redo panel */
bool ED_undo_is_valid(const bContext *C, const char *undoname)
{
- Object *obedit = CTX_data_edit_object(C);
- Object *obact = CTX_data_active_object(C);
- ScrArea *sa = CTX_wm_area(C);
-
- if (sa && sa->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
-
- if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) || (sima->mode == SI_MODE_PAINT)) {
- return 1;
- }
- }
-
- if (sa && (sa->spacetype == SPACE_TEXT)) {
- return 1;
- }
- else if (obedit) {
- if (OB_TYPE_SUPPORT_EDITMODE(obedit->type)) {
- return undo_editmode_is_valid(undoname);
- }
- }
- else {
-
- /* if below tests fail, global undo gets executed */
-
- if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
- if (ED_undo_paint_is_valid(UNDO_PAINT_IMAGE, undoname))
- return 1;
- }
- else if (obact && obact->mode & OB_MODE_SCULPT) {
- if (ED_undo_paint_is_valid(UNDO_PAINT_MESH, undoname))
- return 1;
- }
- else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
- return PE_undo_is_valid(CTX_data_scene(C), CTX_data_view_layer(C));
- }
-
- if (U.uiflag & USER_GLOBALUNDO) {
- return BKE_undo_is_valid(undoname);
- }
- }
- return 0;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ return BKE_undosys_stack_has_undo(wm->undo_stack, undoname);
+}
+
+/**
+ * Ideally we wont access the stack directly,
+ * this is needed for modes which handle undo themselves (bypassing #ED_undo_push).
+ *
+ * Using global isn't great, this just avoids doing inline,
+ * causing 'BKE_global.h' & 'BKE_main.h' includes.
+ */
+UndoStack *ED_undo_stack_get(void)
+{
+ wmWindowManager *wm = G.main->wm.first;
+ return wm->undo_stack;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Undo, Undo Push & Redo Operators
+ * \{ */
+
static int ed_undo_exec(bContext *C, wmOperator *UNUSED(op))
{
/* "last operator" should disappear, later we can tie this with undo stack nicer */
@@ -342,19 +245,17 @@ static int ed_undo_redo_exec(bContext *C, wmOperator *UNUSED(op))
static int ed_undo_redo_poll(bContext *C)
{
wmOperator *last_op = WM_operator_last_redo(C);
- return last_op && ED_operator_screenactive(C) &&
+ return last_op && ED_operator_screenactive(C) &&
WM_operator_check_ui_enabled(C, last_op->type->name);
}
-/* ********************** */
-
void ED_OT_undo(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Undo";
ot->description = "Undo previous action";
ot->idname = "ED_OT_undo";
-
+
/* api callbacks */
ot->exec = ed_undo_exec;
ot->poll = ED_operator_screenactive;
@@ -366,7 +267,7 @@ void ED_OT_undo_push(wmOperatorType *ot)
ot->name = "Undo Push";
ot->description = "Add an undo state (internal use only)";
ot->idname = "ED_OT_undo_push";
-
+
/* api callbacks */
ot->exec = ed_undo_push_exec;
@@ -381,7 +282,7 @@ void ED_OT_redo(wmOperatorType *ot)
ot->name = "Redo";
ot->description = "Redo previous action";
ot->idname = "ED_OT_redo";
-
+
/* api callbacks */
ot->exec = ed_redo_exec;
ot->poll = ED_operator_screenactive;
@@ -393,18 +294,25 @@ void ED_OT_undo_redo(wmOperatorType *ot)
ot->name = "Undo and Redo";
ot->description = "Undo and redo previous action";
ot->idname = "ED_OT_undo_redo";
-
+
/* api callbacks */
ot->exec = ed_undo_redo_exec;
ot->poll = ed_undo_redo_poll;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Operator Repeat
+ * \{ */
+
/* ui callbacks should call this rather than calling WM_operator_repeat() themselves */
int ED_undo_operator_repeat(bContext *C, struct wmOperator *op)
{
int ret = 0;
if (op) {
+ CLOG_INFO(&LOG, 1, "idname='%s'", op->type->idname);
wmWindowManager *wm = CTX_wm_manager(C);
struct Scene *scene = CTX_data_scene(C);
@@ -465,9 +373,7 @@ int ED_undo_operator_repeat(bContext *C, struct wmOperator *op)
CTX_wm_region_set(C, ar);
}
else {
- if (G.debug & G_DEBUG) {
- printf("redo_cb: ED_undo_operator_repeat called with NULL 'op'\n");
- }
+ CLOG_WARN(&LOG, "called with NULL 'op'");
}
return ret;
@@ -484,114 +390,50 @@ void ED_undo_operator_repeat_cb_evt(bContext *C, void *arg_op, int UNUSED(arg_ev
ED_undo_operator_repeat(C, (wmOperator *)arg_op);
}
+/** \} */
-/* ************************** */
-
-enum {
- UNDOSYSTEM_GLOBAL = 1,
- UNDOSYSTEM_EDITMODE = 2,
- UNDOSYSTEM_PARTICLE = 3,
- UNDOSYSTEM_IMAPAINT = 4,
- UNDOSYSTEM_SCULPT = 5,
-};
-
-static int get_undo_system(bContext *C)
-{
- Object *obact = CTX_data_active_object(C);
- Object *obedit = CTX_data_edit_object(C);
- ScrArea *sa = CTX_wm_area(C);
-
- /* first check for editor undo */
- if (sa && (sa->spacetype == SPACE_IMAGE)) {
- SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
-
- if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) || (sima->mode == SI_MODE_PAINT)) {
- if (!ED_undo_paint_empty(UNDO_PAINT_IMAGE))
- return UNDOSYSTEM_IMAPAINT;
- }
- }
- /* find out which undo system */
- if (obedit) {
- if (OB_TYPE_SUPPORT_EDITMODE(obedit->type)) {
- return UNDOSYSTEM_EDITMODE;
- }
- }
- else {
- if (obact) {
- if (obact->mode & OB_MODE_PARTICLE_EDIT)
- return UNDOSYSTEM_PARTICLE;
- else if (obact->mode & OB_MODE_TEXTURE_PAINT) {
- if (!ED_undo_paint_empty(UNDO_PAINT_IMAGE))
- return UNDOSYSTEM_IMAPAINT;
- }
- else if (obact->mode & OB_MODE_SCULPT) {
- if (!ED_undo_paint_empty(UNDO_PAINT_MESH))
- return UNDOSYSTEM_SCULPT;
- }
- }
- if (U.uiflag & USER_GLOBALUNDO)
- return UNDOSYSTEM_GLOBAL;
- }
-
- return 0;
-}
+/* -------------------------------------------------------------------- */
+/** \name Undo History Operator
+ * \{ */
/* create enum based on undo items */
-static const EnumPropertyItem *rna_undo_itemf(bContext *C, int undosys, int *totitem)
+static const EnumPropertyItem *rna_undo_itemf(bContext *C, int *totitem)
{
EnumPropertyItem item_tmp = {0}, *item = NULL;
int i = 0;
- bool active;
-
- while (true) {
- const char *name = NULL;
-
- if (undosys == UNDOSYSTEM_PARTICLE) {
- name = PE_undo_get_name(CTX_data_scene(C), CTX_data_view_layer(C), i, &active);
- }
- else if (undosys == UNDOSYSTEM_EDITMODE) {
- name = undo_editmode_get_name(C, i, &active);
- }
- else if (undosys == UNDOSYSTEM_IMAPAINT) {
- name = ED_undo_paint_get_name(C, UNDO_PAINT_IMAGE, i, &active);
- }
- else if (undosys == UNDOSYSTEM_SCULPT) {
- name = ED_undo_paint_get_name(C, UNDO_PAINT_MESH, i, &active);
- }
- else {
- name = BKE_undo_get_name(i, &active);
- }
-
- if (name) {
- item_tmp.identifier = name;
- /* XXX This won't work with non-default contexts (e.g. operators) :/ */
- item_tmp.name = IFACE_(name);
- if (active)
+
+ wmWindowManager *wm = CTX_wm_manager(C);
+ if (wm->undo_stack == NULL) {
+ return NULL;
+ }
+
+ for (UndoStep *us = wm->undo_stack->steps.first; us; us = us->next, i++) {
+ if (us->skip == false) {
+ item_tmp.identifier = us->name;
+ item_tmp.name = IFACE_(us->name);
+ if (us == wm->undo_stack->step_active) {
item_tmp.icon = ICON_RESTRICT_VIEW_OFF;
- else
+ }
+ else {
item_tmp.icon = ICON_NONE;
- item_tmp.value = i++;
+ }
+ item_tmp.value = i;
RNA_enum_item_add(&item, totitem, &item_tmp);
}
- else
- break;
}
-
RNA_enum_item_end(&item, totitem);
-
+
return item;
}
static int undo_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- int undosys, totitem = 0;
-
- undosys = get_undo_system(C);
-
- if (undosys) {
- const EnumPropertyItem *item = rna_undo_itemf(C, undosys, &totitem);
-
+ int totitem = 0;
+
+ {
+ const EnumPropertyItem *item = rna_undo_itemf(C, &totitem);
+
if (totitem > 0) {
uiPopupMenu *pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
uiLayout *layout = UI_popup_menu_layout(pup);
@@ -600,7 +442,7 @@ static int undo_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
const int col_size = 20 + totitem / 12;
int i, c;
bool add_col = true;
-
+
for (c = 0, i = totitem; i--;) {
if (add_col && !(c % col_size)) {
column = uiLayoutColumn(split, false);
@@ -612,12 +454,12 @@ static int undo_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
add_col = true;
}
}
-
+
MEM_freeN((void *)item);
-
+
UI_popup_menu_end(C, pup);
}
-
+
}
return OPERATOR_CANCELLED;
}
@@ -625,30 +467,12 @@ static int undo_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
/* note: also check ed_undo_step() in top if you change notifiers */
static int undo_history_exec(bContext *C, wmOperator *op)
{
- if (RNA_struct_property_is_set(op->ptr, "item")) {
- int undosys = get_undo_system(C);
- int item = RNA_int_get(op->ptr, "item");
-
- if (undosys == UNDOSYSTEM_PARTICLE) {
- PE_undo_number(CTX_data_scene(C), CTX_data_view_layer(C), item);
- }
- else if (undosys == UNDOSYSTEM_EDITMODE) {
- undo_editmode_number(C, item + 1);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
- }
- else if (undosys == UNDOSYSTEM_IMAPAINT) {
- ED_undo_paint_step_num(C, UNDO_PAINT_IMAGE, item);
- }
- else if (undosys == UNDOSYSTEM_SCULPT) {
- ED_undo_paint_step_num(C, UNDO_PAINT_MESH, item);
- }
- else {
- ED_viewport_render_kill_jobs(CTX_wm_manager(C), CTX_data_main(C), true);
- BKE_undo_number(C, item);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
- }
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "item");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ int item = RNA_property_int_get(op->ptr, prop);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ BKE_undosys_step_undo_from_index(wm->undo_stack, C, item);
WM_event_add_notifier(C, NC_WINDOW, NULL);
-
return OPERATOR_FINISHED;
}
return OPERATOR_CANCELLED;
@@ -660,14 +484,14 @@ void ED_OT_undo_history(wmOperatorType *ot)
ot->name = "Undo History";
ot->description = "Redo specific action in history";
ot->idname = "ED_OT_undo_history";
-
+
/* api callbacks */
ot->invoke = undo_history_invoke;
ot->exec = undo_history_exec;
ot->poll = ED_operator_screenactive;
-
+
RNA_def_int(ot->srna, "item", 0, 0, INT_MAX, "Item", "", 0, INT_MAX);
}
-
+/** \} */
diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c
new file mode 100644
index 00000000000..511f4bc72f1
--- /dev/null
+++ b/source/blender/editors/undo/memfile_undo.c
@@ -0,0 +1,151 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/undo/memfile_undo.c
+ * \ingroup edundo
+ *
+ * Wrapper between 'ED_undo.h' and 'BKE_undo_system.h' API's.
+ */
+
+#include "BLI_utildefines.h"
+#include "BLI_sys_types.h"
+
+#include "DNA_object_enums.h"
+
+#include "BKE_blender_undo.h"
+#include "BKE_context.h"
+#include "BKE_undo_system.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_object.h"
+#include "ED_undo.h"
+#include "ED_render.h"
+
+
+#include "../blenloader/BLO_undofile.h"
+
+#include "undo_intern.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Implements ED Undo System
+ * \{ */
+
+typedef struct MemFileUndoStep {
+ UndoStep step;
+ MemFileUndoData *data;
+} MemFileUndoStep;
+
+static bool memfile_undosys_poll(bContext *UNUSED(C))
+{
+ /* other poll functions must run first, this is a catch-all. */
+
+ if ((U.uiflag & USER_GLOBALUNDO) == 0) {
+ return false;
+ }
+ return true;
+}
+
+static bool memfile_undosys_step_encode(struct bContext *C, UndoStep *us_p)
+{
+ MemFileUndoStep *us = (MemFileUndoStep *)us_p;
+
+ /* Important we only use 'main' from the context (see: BKE_undosys_stack_init_from_main). */
+ struct Main *bmain = CTX_data_main(C);
+ UndoStack *ustack = ED_undo_stack_get();
+
+ /* can be NULL, use when set. */
+ MemFileUndoStep *us_prev = (MemFileUndoStep *)BKE_undosys_step_find_by_type(ustack, BKE_UNDOSYS_TYPE_MEMFILE);
+ us->data = BKE_memfile_undo_encode(bmain, us_prev ? us_prev->data : NULL);
+ us->step.data_size = us->data->undo_size;
+
+ return true;
+}
+
+static void memfile_undosys_step_decode(struct bContext *C, UndoStep *us_p, int UNUSED(dir))
+{
+ /* Loading the content will correctly switch into compatible non-object modes. */
+ ED_object_mode_set(C, OB_MODE_OBJECT);
+
+ /* This is needed so undoing/redoing doesn't crash with threaded previews going */
+ ED_viewport_render_kill_jobs(CTX_wm_manager(C), CTX_data_main(C), true);
+ MemFileUndoStep *us = (MemFileUndoStep *)us_p;
+ BKE_memfile_undo_decode(us->data, C);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
+}
+
+static void memfile_undosys_step_free(UndoStep *us_p)
+{
+ /* To avoid unnecessary slow down, free backwards (so we don't need to merge when clearing all). */
+ MemFileUndoStep *us = (MemFileUndoStep *)us_p;
+ if (us_p->next != NULL) {
+ UndoStep *us_next_p = BKE_undosys_step_same_type_next(us_p);
+ if (us_next_p != NULL) {
+ MemFileUndoStep *us_next = (MemFileUndoStep *)us_next_p;
+ BLO_memfile_merge(&us->data->memfile, &us_next->data->memfile);
+ }
+ }
+
+ BKE_memfile_undo_free(us->data);
+}
+
+/* Export for ED_undo_sys. */
+void ED_memfile_undosys_type(UndoType *ut)
+{
+ ut->name = "Global Undo";
+ ut->poll = memfile_undosys_poll;
+ ut->step_encode = memfile_undosys_step_encode;
+ ut->step_decode = memfile_undosys_step_decode;
+ ut->step_free = memfile_undosys_step_free;
+
+ ut->mode = BKE_UNDOTYPE_MODE_STORE;
+ ut->use_context = true;
+
+ ut->step_size = sizeof(MemFileUndoStep);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Utilities
+ * \{ */
+
+/**
+ * Ideally we wouldn't need to export global undo internals, there are some cases where it's needed though.
+ */
+static struct MemFile *ed_undosys_step_get_memfile(UndoStep *us_p)
+{
+ MemFileUndoStep *us = (MemFileUndoStep *)us_p;
+ return &us->data->memfile;
+}
+
+struct MemFile *ED_undosys_stack_memfile_get_active(UndoStack *ustack)
+{
+ UndoStep *us = BKE_undosys_stack_active_with_type(ustack, BKE_UNDOSYS_TYPE_MEMFILE);
+ if (us) {
+ return ed_undosys_step_get_memfile(us);
+ }
+ return NULL;
+}
+
+
+/** \} */
diff --git a/source/blender/editors/util/util_intern.h b/source/blender/editors/undo/undo_intern.h
index 0f650330951..671f9637d65 100644
--- a/source/blender/editors/util/util_intern.h
+++ b/source/blender/editors/undo/undo_intern.h
@@ -15,32 +15,21 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) 2008 Blender Foundation.
- * All rights reserved.
- *
- *
- * Contributor(s): Blender Foundation
- *
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/editors/util/util_intern.h
- * \ingroup edutil
+/** \file blender/editors/undo/undo_intern.h
+ * \ingroup edundo
*/
-
-#ifndef __UTIL_INTERN_H__
-#define __UTIL_INTERN_H__
+#ifndef __UNDO_INTERN_H__
+#define __UNDO_INTERN_H__
/* internal exports only */
-/* editmode_undo.c */
-void undo_editmode_name(struct bContext *C, const char *undoname);
-bool undo_editmode_is_valid(const char *undoname);
-const char *undo_editmode_get_name(struct bContext *C, int nr, bool *r_active);
-void *undo_editmode_get_prev(struct Object *ob);
-void undo_editmode_step(struct bContext *C, int step);
-void undo_editmode_number(struct bContext *C, int nr);
+struct UndoType;
-#endif /* __UTIL_INTERN_H__ */
+/* memfile_undo.c */
+void ED_memfile_undosys_type(struct UndoType *ut);
+#endif /* __UNDO_INTERN_H__ */
diff --git a/source/blender/editors/undo/undo_system_types.c b/source/blender/editors/undo/undo_system_types.c
new file mode 100644
index 00000000000..75c3d2cc1b7
--- /dev/null
+++ b/source/blender/editors/undo/undo_system_types.c
@@ -0,0 +1,74 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/undo/undo_system_types.c
+ * \ingroup edundo
+ */
+
+#include <string.h>
+
+#include "BLI_utildefines.h"
+
+
+#include "ED_armature.h"
+#include "ED_curve.h"
+#include "ED_lattice.h"
+#include "ED_mball.h"
+#include "ED_mesh.h"
+#include "ED_paint.h"
+#include "ED_particle.h"
+#include "ED_sculpt.h"
+#include "ED_text.h"
+#include "ED_undo.h"
+#include "undo_intern.h"
+
+/* Keep last */
+#include "BKE_undo_system.h"
+
+void ED_undosys_type_init(void)
+{
+ /* Edit Modes */
+ BKE_undosys_type_append(ED_armature_undosys_type);
+ BKE_undosys_type_append(ED_curve_undosys_type);
+ BKE_undosys_type_append(ED_font_undosys_type);
+ BKE_undosys_type_append(ED_lattice_undosys_type);
+ BKE_undosys_type_append(ED_mball_undosys_type);
+ BKE_undosys_type_append(ED_mesh_undosys_type);
+
+ /* Paint Modes */
+ BKE_UNDOSYS_TYPE_IMAGE = BKE_undosys_type_append(ED_image_undosys_type);
+
+ BKE_UNDOSYS_TYPE_SCULPT = BKE_undosys_type_append(ED_sculpt_undosys_type);
+
+ BKE_UNDOSYS_TYPE_PARTICLE = BKE_undosys_type_append(ED_particle_undosys_type);
+
+ BKE_UNDOSYS_TYPE_PAINTCURVE = BKE_undosys_type_append(ED_paintcurve_undosys_type);
+
+ /* Text editor */
+ BKE_UNDOSYS_TYPE_TEXT = BKE_undosys_type_append(ED_text_undosys_type);
+
+ /* Keep global undo last (as a fallback). */
+ BKE_UNDOSYS_TYPE_MEMFILE = BKE_undosys_type_append(ED_memfile_undosys_type);
+}
+
+void ED_undosys_type_free(void)
+{
+ BKE_undosys_type_free_all();
+}
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index 71a3322cb50..24cfde90804 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -31,6 +31,7 @@ set(INC
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/clog
../../../../intern/glew-mx
)
@@ -41,11 +42,8 @@ set(INC_SYS
set(SRC
ed_transverts.c
ed_util.c
- editmode_undo.c
numinput.c
- undo.c
- util_intern.h
# general includes
../include/BIF_gl.h
../include/BIF_glutil.h
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index b52cc20f71f..d3a9c22bc73 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -35,6 +35,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_armature_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
@@ -58,6 +59,9 @@
#include "BKE_packedFile.h"
#include "BKE_paint.h"
#include "BKE_screen.h"
+#include "BKE_workspace.h"
+#include "BKE_layer.h"
+#include "BKE_undo_system.h"
#include "ED_armature.h"
#include "ED_buttons.h"
@@ -85,12 +89,12 @@
void ED_editors_init(bContext *C)
{
- wmWindowManager *wm = CTX_wm_manager(C);
Main *bmain = CTX_data_main(C);
- Scene *sce = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob, *obact = (view_layer && view_layer->basact) ? view_layer->basact->object : NULL;
- ID *data;
+ wmWindowManager *wm = CTX_wm_manager(C);
+
+ if (wm->undo_stack == NULL) {
+ wm->undo_stack = BKE_undosys_stack_create();
+ }
/* This is called during initialization, so we don't want to store any reports */
ReportList *reports = CTX_wm_reports(C);
@@ -101,24 +105,30 @@ void ED_editors_init(bContext *C)
/* toggle on modes for objects that were saved with these enabled. for
* e.g. linked objects we have to ensure that they are actually the
* active object in this scene. */
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- int mode = ob->mode;
+ Object *obact = CTX_data_active_object(C);
+ if (obact != NULL) {
+ for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
+ int mode = ob->mode;
- if (mode == OB_MODE_OBJECT) {
- /* pass */
- }
- else {
- data = ob->data;
- ob->mode = OB_MODE_OBJECT;
- if ((ob == obact) && !ID_IS_LINKED(ob) && !(data && ID_IS_LINKED(data))) {
- ED_object_toggle_modes(C, mode);
+ if (mode == OB_MODE_OBJECT) {
+ /* pass */
+ }
+ else {
+ ID *data = ob->data;
+ ob->mode = OB_MODE_OBJECT;
+ if ((ob == obact) && !ID_IS_LINKED(ob) && !(data && ID_IS_LINKED(data))) {
+ ED_object_mode_toggle(C, mode);
+ }
}
}
}
/* image editor paint mode */
- if (sce) {
- ED_space_image_paint_update(wm, sce);
+ {
+ Scene *sce = CTX_data_scene(C);
+ if (sce) {
+ ED_space_image_paint_update(wm, sce);
+ }
}
SWAP(int, reports->flag, reports_flag_prev);
@@ -128,31 +138,33 @@ void ED_editors_init(bContext *C)
void ED_editors_exit(bContext *C)
{
Main *bmain = CTX_data_main(C);
- Scene *sce;
if (!bmain)
return;
-
+
/* frees all editmode undos */
- undo_editmode_clear();
- ED_undo_paint_free();
-
- for (sce = bmain->scene.first; sce; sce = sce->id.next) {
- if (sce->obedit) {
- Object *ob = sce->obedit;
-
- if (ob) {
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- if (me->edit_btmesh) {
- EDBM_mesh_free(me->edit_btmesh);
- MEM_freeN(me->edit_btmesh);
- me->edit_btmesh = NULL;
- }
- }
- else if (ob->type == OB_ARMATURE) {
- ED_armature_edit_free(ob->data);
- }
+ if (G.main->wm.first) {
+ wmWindowManager *wm = G.main->wm.first;
+ /* normally we don't check for NULL undo stack, do here since it may run in different context. */
+ if (wm->undo_stack) {
+ BKE_undosys_stack_destroy(wm->undo_stack);
+ wm->undo_stack = NULL;
+ }
+ }
+
+ for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ if (me->edit_btmesh) {
+ EDBM_mesh_free(me->edit_btmesh);
+ MEM_freeN(me->edit_btmesh);
+ me->edit_btmesh = NULL;
+ }
+ }
+ else if (ob->type == OB_ARMATURE) {
+ bArmature *arm = ob->data;
+ if (arm->edbo) {
+ ED_armature_edit_free(ob->data);
}
}
}
@@ -175,18 +187,22 @@ bool ED_editors_flush_edits(const bContext *C, bool for_render)
* objects can exist at the same time */
for (ob = bmain->object.first; ob; ob = ob->id.next) {
if (ob->mode & OB_MODE_SCULPT) {
- /* flush multires changes (for sculpt) */
- multires_force_update(ob);
- has_edited = true;
-
- if (for_render) {
- /* flush changes from dynamic topology sculpt */
- BKE_sculptsession_bm_to_me_for_render(ob);
- }
- else {
- /* Set reorder=false so that saving the file doesn't reorder
- * the BMesh's elements */
- BKE_sculptsession_bm_to_me(ob, false);
+ /* Don't allow flushing while in the middle of a stroke (frees data in use).
+ * Auto-save prevents this from happening but scripts may cause a flush on saving: T53986. */
+ if ((ob->sculpt && ob->sculpt->cache) == 0) {
+ /* flush multires changes (for sculpt) */
+ multires_force_update(ob);
+ has_edited = true;
+
+ if (for_render) {
+ /* flush changes from dynamic topology sculpt */
+ BKE_sculptsession_bm_to_me_for_render(ob);
+ }
+ else {
+ /* Set reorder=false so that saving the file doesn't reorder
+ * the BMesh's elements */
+ BKE_sculptsession_bm_to_me(ob, false);
+ }
}
}
else if (ob->mode & OB_MODE_EDIT) {
diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c
deleted file mode 100644
index d9f777771a8..00000000000
--- a/source/blender/editors/util/editmode_undo.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2004 Blender Foundation
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/util/editmode_undo.c
- * \ingroup edutil
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_object_types.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_blender_undo.h"
-#include "BKE_context.h"
-#include "BKE_global.h"
-
-#include "DEG_depsgraph.h"
-
-#include "ED_util.h"
-#include "ED_mesh.h"
-
-
-#include "util_intern.h"
-
-/* ***************** generic editmode undo system ********************* */
-/*
- * Add this in your local code:
- *
- * void undo_editmode_push(bContext *C, const char *name,
- * void * (*getdata)(bContext *C), // use context to retrieve current editdata
- * void (*freedata)(void *), // pointer to function freeing data
- * void (*to_editmode)(void *, void *), // data to editmode conversion
- * void * (*from_editmode)(void *)) // editmode to data conversion
- * int (*validate_undo)(void *, void *)) // check if undo data is still valid
- *
- *
- * Further exported for UI is:
- *
- * void undo_editmode_step(bContext *C, int step); // undo and redo
- * void undo_editmode_clear(void) // free & clear all data
- * void undo_editmode_menu(void) // history menu
- */
-
-/* ********************************************************************* */
-
-/* ****** XXX ***** */
-static void error(const char *UNUSED(arg)) {}
-/* ****** XXX ***** */
-
-typedef struct UndoElem {
- struct UndoElem *next, *prev;
- ID id; // copy of editmode object ID
- Object *ob; // pointer to edited object
- int type; // type of edited object
- void *undodata;
- uintptr_t undosize;
- char name[BKE_UNDO_STR_MAX];
- void * (*getdata)(bContext * C);
- void (*freedata)(void *);
- void (*to_editmode)(void *, void *, void *);
- void * (*from_editmode)(void *, void *);
- int (*validate_undo)(void *, void *);
-} UndoElem;
-
-static ListBase undobase = {NULL, NULL};
-static UndoElem *curundo = NULL;
-
-
-/* ********************* xtern api calls ************* */
-
-static void undo_restore(UndoElem *undo, void *editdata, void *obdata)
-{
- if (undo) {
- undo->to_editmode(undo->undodata, editdata, obdata);
- }
-}
-
-/* name can be a dynamic string */
-void undo_editmode_push(bContext *C, const char *name,
- void * (*getdata)(bContext * C),
- void (*freedata)(void *),
- void (*to_editmode)(void *, void *, void *),
- void *(*from_editmode)(void *, void *),
- int (*validate_undo)(void *, void *))
-{
- UndoElem *uel;
- Object *obedit = CTX_data_edit_object(C);
- void *editdata;
- int nr;
- uintptr_t memused, totmem, maxmem;
-
- /* at first here was code to prevent an "original" key to be inserted twice
- * this was giving conflicts for example when mesh changed due to keys or apply */
-
- /* remove all undos after (also when curundo == NULL) */
- while (undobase.last != curundo) {
- uel = undobase.last;
- uel->freedata(uel->undodata);
- BLI_freelinkN(&undobase, uel);
- }
-
- /* make new */
- curundo = uel = MEM_callocN(sizeof(UndoElem), "undo editmode");
- BLI_strncpy(uel->name, name, sizeof(uel->name));
- BLI_addtail(&undobase, uel);
-
- uel->getdata = getdata;
- uel->freedata = freedata;
- uel->to_editmode = to_editmode;
- uel->from_editmode = from_editmode;
- uel->validate_undo = validate_undo;
-
- /* limit amount to the maximum amount*/
- nr = 0;
- uel = undobase.last;
- while (uel) {
- nr++;
- if (nr == U.undosteps) break;
- uel = uel->prev;
- }
- if (uel) {
- while (undobase.first != uel) {
- UndoElem *first = undobase.first;
- first->freedata(first->undodata);
- BLI_freelinkN(&undobase, first);
- }
- }
-
- /* copy */
- memused = MEM_get_memory_in_use();
- editdata = getdata(C);
- curundo->undodata = curundo->from_editmode(editdata, obedit->data);
- curundo->undosize = MEM_get_memory_in_use() - memused;
- curundo->ob = obedit;
- curundo->id = obedit->id;
- curundo->type = obedit->type;
-
- if (U.undomemory != 0) {
- /* limit to maximum memory (afterwards, we can't know in advance) */
- totmem = 0;
- maxmem = ((uintptr_t)U.undomemory) * 1024 * 1024;
-
- uel = undobase.last;
- while (uel && uel->prev) {
- totmem += uel->undosize;
- if (totmem > maxmem) break;
- uel = uel->prev;
- }
-
- if (uel) {
- if (uel->prev && uel->prev->prev)
- uel = uel->prev;
-
- while (undobase.first != uel) {
- UndoElem *first = undobase.first;
- first->freedata(first->undodata);
- BLI_freelinkN(&undobase, first);
- }
- }
- }
-}
-
-/* helper to remove clean other objects from undo stack */
-static void undo_clean_stack(bContext *C)
-{
- UndoElem *uel, *next;
- Object *obedit = CTX_data_edit_object(C);
-
- /* global undo changes pointers, so we also allow identical names */
- /* side effect: when deleting/renaming object and start editing new one with same name */
-
- uel = undobase.first;
- while (uel) {
- void *editdata = uel->getdata(C);
- bool is_valid = false;
- next = uel->next;
-
- /* for when objects are converted, renamed, or global undo changes pointers... */
- if (uel->type == obedit->type) {
- if (STREQ(uel->id.name, obedit->id.name)) {
- if (uel->validate_undo == NULL)
- is_valid = true;
- else if (uel->validate_undo(uel->undodata, editdata))
- is_valid = true;
- }
- }
- if (is_valid)
- uel->ob = obedit;
- else {
- if (uel == curundo)
- curundo = NULL;
-
- uel->freedata(uel->undodata);
- BLI_freelinkN(&undobase, uel);
- }
-
- uel = next;
- }
-
- if (curundo == NULL) curundo = undobase.last;
-}
-
-/* 1 = an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation */
-void undo_editmode_step(bContext *C, int step)
-{
- Object *obedit = CTX_data_edit_object(C);
-
- /* prevent undo to happen on wrong object, stack can be a mix */
- undo_clean_stack(C);
-
- if (step == 0) {
- undo_restore(curundo, curundo->getdata(C), obedit->data);
- }
- else if (step == 1) {
-
- if (curundo == NULL || curundo->prev == NULL) {
- error("No more steps to undo");
- }
- else {
- if (G.debug & G_DEBUG) printf("undo %s\n", curundo->name);
- curundo = curundo->prev;
- undo_restore(curundo, curundo->getdata(C), obedit->data);
- }
- }
- else {
- /* curundo has to remain current situation! */
-
- if (curundo == NULL || curundo->next == NULL) {
- error("No more steps to redo");
- }
- else {
- undo_restore(curundo->next, curundo->getdata(C), obedit->data);
- curundo = curundo->next;
- if (G.debug & G_DEBUG) printf("redo %s\n", curundo->name);
- }
- }
-
- /* special case for editmesh, mode must be copied back to the scene */
- if (obedit->type == OB_MESH) {
- EDBM_selectmode_to_scene(C);
- }
-
- DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
-
- /* XXX notifiers */
-}
-
-void undo_editmode_clear(void)
-{
- UndoElem *uel;
-
- uel = undobase.first;
- while (uel) {
- uel->freedata(uel->undodata);
- uel = uel->next;
- }
- BLI_freelistN(&undobase);
- curundo = NULL;
-}
-
-/* based on index nr it does a restore */
-void undo_editmode_number(bContext *C, int nr)
-{
- UndoElem *uel;
- int a = 1;
-
- for (uel = undobase.first; uel; uel = uel->next, a++) {
- if (a == nr) break;
- }
- curundo = uel;
- undo_editmode_step(C, 0);
-}
-
-void undo_editmode_name(bContext *C, const char *undoname)
-{
- UndoElem *uel;
-
- for (uel = undobase.last; uel; uel = uel->prev) {
- if (STREQ(undoname, uel->name))
- break;
- }
- if (uel && uel->prev) {
- curundo = uel->prev;
- undo_editmode_step(C, 0);
- }
-}
-
-/* undoname optionally, if NULL it just checks for existing undo steps */
-bool undo_editmode_is_valid(const char *undoname)
-{
- if (undoname) {
- UndoElem *uel;
-
- for (uel = undobase.last; uel; uel = uel->prev) {
- if (STREQ(undoname, uel->name))
- break;
- }
- return uel != NULL;
- }
- return undobase.last != undobase.first;
-}
-
-
-/* get name of undo item, return null if no item with this index */
-/* if active pointer, set it to 1 if true */
-const char *undo_editmode_get_name(bContext *C, int nr, bool *r_active)
-{
- UndoElem *uel;
-
- /* prevent wrong numbers to be returned */
- undo_clean_stack(C);
-
- if (r_active) *r_active = false;
-
- uel = BLI_findlink(&undobase, nr);
- if (uel) {
- if (r_active && (uel == curundo)) {
- *r_active = true;
- }
- return uel->name;
- }
- return NULL;
-}
-
-
-void *undo_editmode_get_prev(Object *ob)
-{
- UndoElem *ue = undobase.last;
- if (ue && ue->prev && ue->prev->ob == ob) return ue->prev->undodata;
- return NULL;
-}
diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c
index 0f3240946fd..a139f0e3c87 100644
--- a/source/blender/editors/util/numinput.c
+++ b/source/blender/editors/util/numinput.c
@@ -478,9 +478,9 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
/* At this point, our value has changed, try to interpret it with python (if str is not empty!). */
if (n->str[0]) {
const float val_prev = n->val[idx];
+ double val;
#ifdef WITH_PYTHON
Scene *sce = CTX_data_scene(C);
- double val;
char str_unit_convert[NUM_STR_REP_LEN * 6]; /* Should be more than enough! */
const char *default_unit = NULL;
@@ -506,8 +506,9 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
n->val_flag[idx] |= NUM_INVALID;
}
#else /* Very unlikely, but does not harm... */
- n->val[idx] = (float)atof(n->str);
- (void)C;
+ val = atof(n->str);
+ n->val[idx] = (float)val;
+ UNUSED_VARS(C);
#endif /* WITH_PYTHON */
if (n->val_flag[idx] & NUM_NEGATE) {
diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c
index 6b4dd0f0210..f037783bd5e 100644
--- a/source/blender/editors/uvedit/uvedit_buttons.c
+++ b/source/blender/editors/uvedit/uvedit_buttons.c
@@ -61,7 +61,7 @@
/* UV Utilities */
-static int uvedit_center(Scene *scene, BMEditMesh *em, Image *ima, float center[2])
+static int uvedit_center(Scene *scene, Object *obedit, BMEditMesh *em, Image *ima, float center[2])
{
BMFace *f;
BMLoop *l;
@@ -73,7 +73,7 @@ static int uvedit_center(Scene *scene, BMEditMesh *em, Image *ima, float center[
zero_v2(center);
BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, f))
+ if (!uvedit_face_visible_test(scene, obedit, ima, f))
continue;
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
@@ -93,7 +93,7 @@ static int uvedit_center(Scene *scene, BMEditMesh *em, Image *ima, float center[
return tot;
}
-static void uvedit_translate(Scene *scene, BMEditMesh *em, Image *ima, float delta[2])
+static void uvedit_translate(Scene *scene, Object *obedit, BMEditMesh *em, Image *ima, float delta[2])
{
BMFace *f;
BMLoop *l;
@@ -103,7 +103,7 @@ static void uvedit_translate(Scene *scene, BMEditMesh *em, Image *ima, float del
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, f))
+ if (!uvedit_face_visible_test(scene, obedit, ima, f))
continue;
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
@@ -134,7 +134,7 @@ static void uvedit_vertex_buttons(const bContext *C, uiBlock *block)
em = BKE_editmesh_from_object(obedit);
- if (uvedit_center(scene, em, ima, center)) {
+ if (uvedit_center(scene, obedit, em, ima, center)) {
float range_xy[2][2] = {
{-10.0f, 10.0f},
{-10.0f, 10.0f},
@@ -190,7 +190,7 @@ static void do_uvedit_vertex(bContext *C, void *UNUSED(arg), int event)
em = BKE_editmesh_from_object(obedit);
ED_space_image_get_size(sima, &imx, &imy);
- uvedit_center(scene, em, ima, center);
+ uvedit_center(scene, obedit, em, ima, center);
if (sima->flag & SI_COORDFLOATS) {
delta[0] = uvedit_old_center[0] - center[0];
@@ -201,7 +201,7 @@ static void do_uvedit_vertex(bContext *C, void *UNUSED(arg), int event)
delta[1] = uvedit_old_center[1] / imy - center[1];
}
- uvedit_translate(scene, em, ima, delta);
+ uvedit_translate(scene, obedit, em, ima, delta);
WM_event_add_notifier(C, NC_IMAGE, sima->image);
}
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index f882f3ecd65..3fcc89d0973 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -59,6 +59,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
+#include "GPU_batch.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
@@ -73,7 +74,7 @@
#include "uvedit_intern.h"
-static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset, const uint shdr_pos);
+static void draw_uvs_lineloop_bmfaces(BMesh *bm, const int cd_loop_uv_offset, const uint shdr_pos);
void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
{
@@ -160,8 +161,6 @@ static void draw_uvs_shadow(Object *obedit)
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
- BMFace *efa;
- BMIter iter;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
@@ -172,14 +171,12 @@ static void draw_uvs_shadow(Object *obedit)
/* draws the mesh when painting */
immUniformThemeColor(TH_UV_SHADOW);
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos);
- }
+ draw_uvs_lineloop_bmfaces(bm, cd_loop_uv_offset, pos);
immUnbindProgram();
}
-static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, const BMFace *efa_act)
+static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, Object *obedit, BMEditMesh *em, const BMFace *efa_act)
{
BMesh *bm = em->bm;
BMFace *efa;
@@ -217,7 +214,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, con
totarea += BM_face_calc_area(efa);
totuvarea += area_poly_v2(tf_uv, efa->len);
- if (uvedit_face_visible_test(scene, ima, efa)) {
+ if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
else {
@@ -314,7 +311,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, con
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, ima, efa)) {
+ if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
const int efa_len = efa->len;
float (*tf_uv)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa_len);
float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uvorig_buf, vec2f, efa_len);
@@ -384,18 +381,43 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, con
BLI_buffer_free(&tf_uvorig_buf);
}
-static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset, const uint shdr_pos)
+static void draw_uvs_lineloop_bmfaces(BMesh *bm, const int cd_loop_uv_offset, const uint shdr_pos)
{
- BMIter liter;
+ BMIter iter, liter;
+ BMFace *efa;
BMLoop *l;
MLoopUV *luv;
- immBegin(GWN_PRIM_LINE_LOOP, efa->len);
+ /* For more efficiency first transfer the entire buffer to vram. */
+ Gwn_Batch *uv_batch = immBeginBatchAtMost(GWN_PRIM_LINE_LOOP, bm->totloop);
+
+ BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
+ continue;
+
+ BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ immVertex2fv(shdr_pos, luv->uv);
+ }
+ }
+ immEnd();
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- immVertex2fv(shdr_pos, luv->uv);
+ /* Then draw each face contour separately. */
+ GWN_batch_program_use_begin(uv_batch);
+ unsigned int index = 0;
+ BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
+ continue;
+
+ GWN_batch_draw_range_ex(uv_batch, index, efa->len, false);
+ index += efa->len;
}
+ GWN_batch_program_use_end(uv_batch);
+
+ GWN_vertbuf_discard(uv_batch->verts[0]);
+ GWN_batch_discard(uv_batch);
+
+ immUnbindProgram();
immEnd();
}
@@ -615,7 +637,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
- unsigned char col1[4], col2[4];
+ float col1[4], col2[4];
float pointsize;
int drawfaces, interpedges;
Image *ima = sima->image;
@@ -669,12 +691,12 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
/* 2. draw colored faces */
if (sima->flag & SI_DRAW_STRETCH) {
- draw_uvs_stretch(sima, scene, em, efa_act);
+ draw_uvs_stretch(sima, scene, obedit, em, efa_act);
}
else {
unsigned int tri_count = 0;
BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, ima, efa)) {
+ if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
BM_elem_flag_enable(efa, BM_ELEM_TAG);
tri_count += efa->len - 2;
}
@@ -683,16 +705,16 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
}
}
- if (!(sima->flag & SI_NO_DRAWFACES)) {
+ if (tri_count && !(sima->flag & SI_NO_DRAWFACES)) {
/* draw transparent faces */
- UI_GetThemeColor4ubv(TH_FACE, col1);
- UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ UI_GetThemeColor4fv(TH_FACE, col1);
+ UI_GetThemeColor4fv(TH_FACE_SELECT, col2);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
Gwn_VertFormat *format = immVertexFormat();
pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
@@ -704,12 +726,12 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
if (efa == efa_act) {
/* only once */
- unsigned char tmp_col[4];
- UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, tmp_col);
- immAttrib4ubv(color, tmp_col);
+ float tmp_col[4];
+ UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, tmp_col);
+ immAttrib4fv(color, tmp_col);
}
else {
- immAttrib4ubv(color, is_select ? col2 : col1);
+ immAttrib4fv(color, is_select ? col2 : col1);
}
draw_uvs_looptri(em, &i, cd_loop_uv_offset, pos);
@@ -722,7 +744,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
glDisable(GL_BLEND);
}
else {
- if (efa_act && !uvedit_face_visible_test(scene, ima, efa_act)) {
+ if (efa_act && !uvedit_face_visible_test(scene, obedit, ima, efa_act)) {
efa_act = NULL;
}
}
@@ -736,16 +758,14 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
if (sima->flag & SI_SMOOTH_UV) {
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
- glLineWidth(1);
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
switch (sima->dt_uv) {
case SI_UVDT_DASH:
{
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
-
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
@@ -755,141 +775,160 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
immUniform1i("num_colors", 2); /* "advanced" mode */
immUniformArray4fv("colors", (float *)(float[][4]){{0.56f, 0.56f, 0.56f, 1.0f}, {0.07f, 0.07f, 0.07f, 1.0f}}, 2);
immUniform1f("dash_width", 4.0f);
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
- continue;
-
- draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, shdr_pos);
- }
-
- immUnbindProgram();
+ glLineWidth(1.0f);
break;
}
case SI_UVDT_BLACK: /* black/white */
case SI_UVDT_WHITE:
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
-
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
if (sima->dt_uv == SI_UVDT_WHITE) {
immUniformColor3f(1.0f, 1.0f, 1.0f);
}
else {
immUniformColor3f(0.0f, 0.0f, 0.0f);
}
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
- continue;
-
- draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos);
- }
-
- immUnbindProgram();
+ glLineWidth(1.0f);
break;
case SI_UVDT_OUTLINE:
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
-
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- glLineWidth(3);
imm_cpack(0x0);
+ glLineWidth(3.0f);
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
- continue;
+ break;
+ }
- draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos);
- }
+ /* For more efficiency first transfer the entire buffer to vram. */
+ Gwn_Batch *uv_batch = immBeginBatchAtMost(GWN_PRIM_LINE_LOOP, bm->totloop);
+ Gwn_VertBuf* uv_vbo = uv_batch->verts[0];
+ BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
+ continue;
- immUnbindProgram();
+ BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ immVertex2fv(pos, luv->uv);
+ }
+ }
+ immEnd();
- glLineWidth(1);
- UI_GetThemeColor4ubv(TH_WIRE_EDIT, col2);
+ /* Then draw each face contour separately. */
+ GWN_batch_program_use_begin(uv_batch);
+ unsigned int index = 0, vbo_len_used;
+ BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
+ continue;
- if (me->drawflag & ME_DRAWEDGES) {
- int sel;
- UI_GetThemeColor4ubv(TH_EDGE_SELECT, col1);
+ GWN_batch_draw_range_ex(uv_batch, index, efa->len, false);
+ index += efa->len;
+ }
+ vbo_len_used = index;
+ GWN_batch_program_use_end(uv_batch);
+ immUnbindProgram();
- Gwn_VertFormat *format = immVertexFormat();
- pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
- if (interpedges) {
- immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+ if (sima->dt_uv == SI_UVDT_OUTLINE) {
+ glLineWidth(1.0f);
+ UI_GetThemeColor4fv(TH_WIRE_EDIT, col2);
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
- continue;
+ if (me->drawflag & ME_DRAWEDGES) {
+ int sel;
+ UI_GetThemeColor4fv(TH_EDGE_SELECT, col1);
- immBegin(GWN_PRIM_LINE_LOOP, efa->len);
+ if (interpedges) {
+ /* Create a color buffer. */
+ static Gwn_VertFormat format = {0};
+ static uint shdr_col;
+ if (format.attrib_ct == 0) {
+ shdr_col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ }
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- sel = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
- immAttrib4ubv(color, sel ? (GLubyte *)col1 : (GLubyte *)col2);
+ Gwn_VertBuf *vbo_col = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo_col, vbo_len_used);
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- immVertex2fv(pos, luv->uv);
- }
+ index = 0;
+ BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
+ continue;
- immEnd();
+ BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
+ sel = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
+ GWN_vertbuf_attr_set(vbo_col, shdr_col, index++, sel ? col1 : col2);
}
-
- immUnbindProgram();
}
- else {
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ /* Reuse the UV buffer and add the color buffer. */
+ GWN_batch_vertbuf_add_ex(uv_batch, vbo_col, true);
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- int lastsel = -1;
+ /* Now draw each face contour separately with another builtin program. */
+ GWN_batch_program_set_builtin(uv_batch, GPU_SHADER_2D_SMOOTH_COLOR);
+ gpuBindMatrices(uv_batch->interface);
- if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
- continue;
-
- immBegin(GWN_PRIM_LINES, efa->len * 2);
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- sel = uvedit_edge_select_test(scene, l, cd_loop_uv_offset);
- if (sel != lastsel) {
- immAttrib4ubv(color, sel ? (GLubyte *)col1 : (GLubyte *)col2);
- lastsel = sel;
- }
-
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- immVertex2fv(pos, luv->uv);
- luv = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
- immVertex2fv(pos, luv->uv);
- }
-
- immEnd();
- }
+ GWN_batch_program_use_begin(uv_batch);
+ index = 0;
+ BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
+ continue;
- immUnbindProgram();
+ GWN_batch_draw_range_ex(uv_batch, index, efa->len, false);
+ index += efa->len;
}
+ GWN_batch_program_use_end(uv_batch);
}
else {
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ Gwn_VertFormat *format = immVertexFormat();
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4ubv(col2);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- /* no nice edges */
+ /* Use batch here to avoid problems with `IMM_BUFFER_SIZE`. */
+ Gwn_Batch *flat_edges_batch = immBeginBatchAtMost(GWN_PRIM_LINES, vbo_len_used * 2);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
-
- draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos);
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ sel = uvedit_edge_select_test(scene, l, cd_loop_uv_offset);
+ immAttrib4fv(color, sel ? col1 : col2);
+
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ immVertex2fv(pos, luv->uv);
+ luv = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
+ immVertex2fv(pos, luv->uv);
+ }
}
+ immEnd();
+
+ GWN_batch_draw(flat_edges_batch);
+ GWN_vertbuf_discard(flat_edges_batch->verts[0]);
+ GWN_batch_discard(flat_edges_batch);
immUnbindProgram();
}
+ }
+ else {
+ GWN_batch_uniform_4fv(uv_batch, "color", col2);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- break;
+ /* no nice edges */
+ GWN_batch_program_use_begin(uv_batch);
+ index = 0;
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
+ continue;
+
+ GWN_batch_draw_range_ex(uv_batch, index, efa->len, false);
+ index += efa->len;
+ }
+ GWN_batch_program_use_end(uv_batch);
+ immUnbindProgram();
+ }
}
+ GWN_vertbuf_discard(uv_vbo);
+ GWN_batch_discard(uv_batch);
+
if (sima->flag & SI_SMOOTH_UV) {
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
@@ -903,7 +942,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
Gwn_VertFormat *format = immVertexFormat();
pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
@@ -921,8 +960,8 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
if (!uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
/* Only set color for the first face */
if (!col_set) {
- UI_GetThemeColor3ubv(TH_WIRE, col1);
- immAttrib3ubv(color, col1);
+ UI_GetThemeColor3fv(TH_WIRE, col1);
+ immAttrib3fv(color, col1);
col_set = true;
}
@@ -943,8 +982,8 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
if (uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
/* Only set color for the first face */
if (!col_set) {
- UI_GetThemeColor3ubv(TH_FACE_DOT, col1);
- immAttrib3ubv(color, col1);
+ UI_GetThemeColor3fv(TH_FACE_DOT, col1);
+ immAttrib3fv(color, col1);
col_set = true;
}
@@ -1032,7 +1071,9 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
}
-static void draw_uv_shadows_get(SpaceImage *sima, Object *ob, Object *obedit, bool *show_shadow, bool *show_texpaint)
+static void draw_uv_shadows_get(
+ SpaceImage *sima, Object *ob, Object *obedit,
+ bool *show_shadow, bool *show_texpaint)
{
*show_shadow = *show_texpaint = false;
@@ -1048,7 +1089,9 @@ static void draw_uv_shadows_get(SpaceImage *sima, Object *ob, Object *obedit, bo
*show_texpaint = (ob && ob->type == OB_MESH && ob->mode == OB_MODE_TEXTURE_PAINT);
}
-void ED_uvedit_draw_main(SpaceImage *sima, ARegion *ar, Scene *scene, ViewLayer *view_layer, Object *obedit, Object *obact, Depsgraph *depsgraph)
+void ED_uvedit_draw_main(
+ SpaceImage *sima,
+ ARegion *ar, Scene *scene, ViewLayer *view_layer, Object *obedit, Object *obact, Depsgraph *depsgraph)
{
ToolSettings *toolsettings = scene->toolsettings;
bool show_uvedit, show_uvshadow, show_texpaint_uvshadow;
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index 6ca46941404..c5f16d6fb14 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -50,17 +50,30 @@ void uv_poly_center(struct BMFace *f, float r_cent[2], const int cd_loop_uv_off
/* find nearest */
-typedef struct NearestHit {
+typedef struct UvNearestHit {
+ /** Always set if we have a hit. */
struct BMFace *efa;
struct BMLoop *l;
struct MLoopUV *luv, *luv_next;
- int lindex; /* index of loop within face */
-} NearestHit;
+ /** Index of loop within face. */
+ int lindex;
+ /** Needs to be set before calling nearest functions. */
+ float dist_sq;
+} UvNearestHit;
-void uv_find_nearest_vert(struct Scene *scene, struct Image *ima, struct BMEditMesh *em,
- const float co[2], const float penalty[2], struct NearestHit *hit);
-void uv_find_nearest_edge(struct Scene *scene, struct Image *ima, struct BMEditMesh *em,
- const float co[2], struct NearestHit *hit);
+#define UV_NEAREST_HIT_INIT { .dist_sq = FLT_MAX, }
+
+bool uv_find_nearest_vert(
+ struct Scene *scene, struct Image *ima, struct Object *obedit,
+ const float co[2], const float penalty_dist, struct UvNearestHit *hit_final);
+
+bool uv_find_nearest_edge(
+ struct Scene *scene, struct Image *ima, struct Object *obedit,
+ const float co[2], struct UvNearestHit *hit_final);
+
+bool uv_find_nearest_face(
+ struct Scene *scene, struct Image *ima, struct Object *obedit,
+ const float co[2], struct UvNearestHit *hit_final);
/* utility tool functions */
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 03a5f4dddc8..9df0c7c89ed 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -49,7 +49,7 @@
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
#include "BLI_math.h"
-#include "BLI_lasso.h"
+#include "BLI_lasso_2d.h"
#include "BLI_blenlib.h"
#include "BLI_array.h"
@@ -89,11 +89,13 @@
#include "uvedit_intern.h"
-static void uv_select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int action);
+static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, BMEditMesh *em, int action);
static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object *obedit, const bool select);
static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object *obedit, const bool select);
-/************************* state testing ************************/
+/* -------------------------------------------------------------------- */
+/** \name State Testing
+ * \{ */
bool ED_uvedit_test(Object *obedit)
{
@@ -134,15 +136,21 @@ static int UNUSED_FUNCTION(ED_operator_uvmap_mesh) (bContext *C)
return 0;
}
-/**************************** object active image *****************************/
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Active Image
+ * \{ */
static bool is_image_texture_node(bNode *node)
{
return ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT);
}
-bool ED_object_get_active_image(Object *ob, int mat_nr,
- Image **r_ima, ImageUser **r_iuser, bNode **r_node, bNodeTree **r_ntree)
+bool ED_object_get_active_image(
+ Object *ob, int mat_nr,
+ Image **r_ima, ImageUser **r_iuser, bNode **r_node, bNodeTree **r_ntree)
{
Material *ma = give_current_material(ob, mat_nr);
bNodeTree *ntree = (ma && ma->use_nodes) ? ma->nodetree : NULL;
@@ -175,7 +183,11 @@ void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *i
}
}
-/************************* assign image ************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Assign Image
+ * \{ */
//#define USE_SWITCH_ASPECT
@@ -230,7 +242,7 @@ void ED_uvedit_assign_image(Main *UNUSED(bmain), Scene *scene, Object *obedit, I
/* now assign to all visible faces */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, previma, efa) &&
+ if (uvedit_face_visible_test(scene, obedit, previma, efa) &&
(selected == true || uvedit_face_select_test(scene, efa, cd_loop_uv_offset)))
{
#ifdef USE_SWITCH_ASPECT
@@ -266,7 +278,11 @@ void ED_uvedit_assign_image(Main *UNUSED(bmain), Scene *scene, Object *obedit, I
}
-/*********************** space conversion *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Space Conversion
+ * \{ */
static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist)
{
@@ -284,7 +300,26 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist
dist[1] = pixeldist / height;
}
-/*************** visibility and selection utilities **************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Visibility and Selection Utilities
+ * \{ */
+
+static void uvedit_vertex_select_tagged(BMEditMesh *em, Scene *scene, bool select, int cd_loop_uv_offset)
+{
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ }
+ }
+ }
+}
bool uvedit_face_visible_nolocal(Scene *scene, BMFace *efa)
{
@@ -296,12 +331,12 @@ bool uvedit_face_visible_nolocal(Scene *scene, BMFace *efa)
return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0 && BM_elem_flag_test(efa, BM_ELEM_SELECT));
}
-bool uvedit_face_visible_test(Scene *scene, Image *ima, BMFace *efa)
+bool uvedit_face_visible_test(Scene *scene, Object *obedit, Image *ima, BMFace *efa)
{
ToolSettings *ts = scene->toolsettings;
if (ts->uv_flag & UV_SHOW_SAME_IMAGE) {
- const Image *face_image = BKE_object_material_edit_image_get(scene->obedit, efa->mat_nr);
+ const Image *face_image = BKE_object_material_edit_image_get(obedit, efa->mat_nr);
return (face_image == ima) ? uvedit_face_visible_nolocal(scene, efa) : false;
}
else {
@@ -309,8 +344,9 @@ bool uvedit_face_visible_test(Scene *scene, Image *ima, BMFace *efa)
}
}
-bool uvedit_face_select_test(Scene *scene, BMFace *efa,
- const int cd_loop_uv_offset)
+bool uvedit_face_select_test(
+ Scene *scene, BMFace *efa,
+ const int cd_loop_uv_offset)
{
ToolSettings *ts = scene->toolsettings;
if (ts->uv_flag & UV_SYNC_SELECTION) {
@@ -331,8 +367,9 @@ bool uvedit_face_select_test(Scene *scene, BMFace *efa,
}
}
-bool uvedit_face_select_set(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa, const bool select,
- const bool do_history, const int cd_loop_uv_offset)
+bool uvedit_face_select_set(
+ struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa, const bool select,
+ const bool do_history, const int cd_loop_uv_offset)
{
if (select) {
return uvedit_face_select_enable(scene, em, efa, do_history, cd_loop_uv_offset);
@@ -342,8 +379,9 @@ bool uvedit_face_select_set(struct Scene *scene, struct BMEditMesh *em, struct B
}
}
-bool uvedit_face_select_enable(Scene *scene, BMEditMesh *em, BMFace *efa, const bool do_history,
- const int cd_loop_uv_offset)
+bool uvedit_face_select_enable(
+ Scene *scene, BMEditMesh *em, BMFace *efa, const bool do_history,
+ const int cd_loop_uv_offset)
{
ToolSettings *ts = scene->toolsettings;
@@ -369,8 +407,9 @@ bool uvedit_face_select_enable(Scene *scene, BMEditMesh *em, BMFace *efa, const
return false;
}
-bool uvedit_face_select_disable(Scene *scene, BMEditMesh *em, BMFace *efa,
- const int cd_loop_uv_offset)
+bool uvedit_face_select_disable(
+ Scene *scene, BMEditMesh *em, BMFace *efa,
+ const int cd_loop_uv_offset)
{
ToolSettings *ts = scene->toolsettings;
@@ -393,8 +432,9 @@ bool uvedit_face_select_disable(Scene *scene, BMEditMesh *em, BMFace *efa,
return false;
}
-bool uvedit_edge_select_test(Scene *scene, BMLoop *l,
- const int cd_loop_uv_offset)
+bool uvedit_edge_select_test(
+ Scene *scene, BMLoop *l,
+ const int cd_loop_uv_offset)
{
ToolSettings *ts = scene->toolsettings;
@@ -420,8 +460,9 @@ bool uvedit_edge_select_test(Scene *scene, BMLoop *l,
}
}
-void uvedit_edge_select_set(BMEditMesh *em, Scene *scene, BMLoop *l, const bool select,
- const bool do_history, const int cd_loop_uv_offset)
+void uvedit_edge_select_set(
+ BMEditMesh *em, Scene *scene, BMLoop *l, const bool select,
+ const bool do_history, const int cd_loop_uv_offset)
{
if (select) {
@@ -432,8 +473,9 @@ void uvedit_edge_select_set(BMEditMesh *em, Scene *scene, BMLoop *l, const bool
}
}
-void uvedit_edge_select_enable(BMEditMesh *em, Scene *scene, BMLoop *l, const bool do_history,
- const int cd_loop_uv_offset)
+void uvedit_edge_select_enable(
+ BMEditMesh *em, Scene *scene, BMLoop *l, const bool do_history,
+ const int cd_loop_uv_offset)
{
ToolSettings *ts = scene->toolsettings;
@@ -463,8 +505,9 @@ void uvedit_edge_select_enable(BMEditMesh *em, Scene *scene, BMLoop *l, const bo
}
}
-void uvedit_edge_select_disable(BMEditMesh *em, Scene *scene, BMLoop *l,
- const int cd_loop_uv_offset)
+void uvedit_edge_select_disable(
+ BMEditMesh *em, Scene *scene, BMLoop *l,
+ const int cd_loop_uv_offset)
{
ToolSettings *ts = scene->toolsettings;
@@ -490,8 +533,9 @@ void uvedit_edge_select_disable(BMEditMesh *em, Scene *scene, BMLoop *l,
}
}
-bool uvedit_uv_select_test(Scene *scene, BMLoop *l,
- const int cd_loop_uv_offset)
+bool uvedit_uv_select_test(
+ Scene *scene, BMLoop *l,
+ const int cd_loop_uv_offset)
{
ToolSettings *ts = scene->toolsettings;
@@ -507,8 +551,9 @@ bool uvedit_uv_select_test(Scene *scene, BMLoop *l,
}
}
-void uvedit_uv_select_set(BMEditMesh *em, Scene *scene, BMLoop *l, const bool select,
- const bool do_history, const int cd_loop_uv_offset)
+void uvedit_uv_select_set(
+ BMEditMesh *em, Scene *scene, BMLoop *l, const bool select,
+ const bool do_history, const int cd_loop_uv_offset)
{
if (select) {
uvedit_uv_select_enable(em, scene, l, do_history, cd_loop_uv_offset);
@@ -518,8 +563,9 @@ void uvedit_uv_select_set(BMEditMesh *em, Scene *scene, BMLoop *l, const bool se
}
}
-void uvedit_uv_select_enable(BMEditMesh *em, Scene *scene, BMLoop *l,
- const bool do_history, const int cd_loop_uv_offset)
+void uvedit_uv_select_enable(
+ BMEditMesh *em, Scene *scene, BMLoop *l,
+ const bool do_history, const int cd_loop_uv_offset)
{
ToolSettings *ts = scene->toolsettings;
@@ -539,8 +585,9 @@ void uvedit_uv_select_enable(BMEditMesh *em, Scene *scene, BMLoop *l,
}
}
-void uvedit_uv_select_disable(BMEditMesh *em, Scene *scene, BMLoop *l,
- const int cd_loop_uv_offset)
+void uvedit_uv_select_disable(
+ BMEditMesh *em, Scene *scene, BMLoop *l,
+ const int cd_loop_uv_offset)
{
ToolSettings *ts = scene->toolsettings;
@@ -556,7 +603,11 @@ void uvedit_uv_select_disable(BMEditMesh *em, Scene *scene, BMLoop *l,
}
}
-/*********************** live unwrap utilities ***********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Live Unwrap Utilities
+ * \{ */
void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *obedit)
{
@@ -567,7 +618,12 @@ void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *obedit)
}
}
-/*********************** geometric utilities ***********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Geometric Utilities
+ * \{ */
+
void uv_poly_center(BMFace *f, float r_cent[2], const int cd_loop_uv_offset)
{
BMLoop *l;
@@ -607,7 +663,7 @@ bool ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2],
INIT_MINMAX2(r_min, r_max);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -653,7 +709,7 @@ static bool ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[
zero_v2(co);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -690,81 +746,100 @@ bool ED_uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], c
return changed;
}
-/************************** find nearest ****************************/
+/** \} */
-void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float co[2], NearestHit *hit)
+/* -------------------------------------------------------------------- */
+/** \name Find Nearest Elements
+ * \{ */
+
+bool uv_find_nearest_edge(
+ Scene *scene, Image *ima, Object *obedit, const float co[2],
+ UvNearestHit *hit)
{
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv, *luv_next;
- float mindist_squared, dist_squared;
int i;
+ bool found = false;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- mindist_squared = 1e10f;
- memset(hit, 0, sizeof(*hit));
-
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
-
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
continue;
-
+ }
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
- dist_squared = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv);
+ const float dist_test_sq = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv);
- if (dist_squared < mindist_squared) {
+ if (dist_test_sq < hit->dist_sq) {
hit->efa = efa;
-
+
hit->l = l;
hit->luv = luv;
hit->luv_next = luv_next;
hit->lindex = i;
- mindist_squared = dist_squared;
+ hit->dist_sq = dist_test_sq;
+ found = true;
}
}
}
+ return found;
}
-static void uv_find_nearest_face(Scene *scene, Image *ima, BMEditMesh *em, const float co[2], NearestHit *hit)
+bool uv_find_nearest_face(
+ Scene *scene, Image *ima, Object *obedit, const float co[2],
+ UvNearestHit *hit_final)
{
- BMFace *efa;
- BMIter iter;
- float mindist, dist, cent[2];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ bool found = false;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- mindist = 1e10f;
- memset(hit, 0, sizeof(*hit));
+ /* this will fill in hit.vert1 and hit.vert2 */
+ float dist_sq_init = hit_final->dist_sq;
+ UvNearestHit hit = *hit_final;
+ if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
+ hit.dist_sq = dist_sq_init;
+ hit.l = NULL;
+ hit.luv = hit.luv_next = NULL;
- /*this will fill in hit.vert1 and hit.vert2*/
- uv_find_nearest_edge(scene, ima, em, co, hit);
- hit->l = NULL;
- hit->luv = hit->luv_next = NULL;
+ BMIter iter;
+ BMFace *efa;
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
- continue;
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
- uv_poly_center(efa, cent, cd_loop_uv_offset);
+ float cent[2];
+ uv_poly_center(efa, cent, cd_loop_uv_offset);
- dist = len_manhattan_v2v2(co, cent);
+ const float dist_test_sq = len_squared_v2v2(co, cent);
- if (dist < mindist) {
- hit->efa = efa;
- mindist = dist;
+ if (dist_test_sq < hit.dist_sq) {
+ hit.efa = efa;
+ hit.dist_sq = dist_test_sq;
+ found = true;
+ }
}
}
+ if (found) {
+ *hit_final = hit;
+ }
+ return found;
}
-static bool uv_nearest_between(const BMLoop *l, const float co[2],
- const int cd_loop_uv_offset)
+static bool uv_nearest_between(
+ const BMLoop *l, const float co[2],
+ const int cd_loop_uv_offset)
{
const float *uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset))->uv;
const float *uv_curr = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset))->uv;
@@ -774,56 +849,73 @@ static bool uv_nearest_between(const BMLoop *l, const float co[2],
(line_point_side_v2(uv_next, uv_curr, co) <= 0.0f));
}
-void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em,
- float const co[2], const float penalty[2], NearestHit *hit)
+bool uv_find_nearest_vert(
+ Scene *scene, Image *ima, Object *obedit,
+ float const co[2], const float penalty_dist, UvNearestHit *hit_final)
{
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
- float mindist, dist;
- int i;
+ bool found = false;
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ /* this will fill in hit.vert1 and hit.vert2 */
+ float dist_sq_init = hit_final->dist_sq;
+ UvNearestHit hit = *hit_final;
+ if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
+ hit.dist_sq = dist_sq_init;
- /*this will fill in hit.vert1 and hit.vert2*/
- uv_find_nearest_edge(scene, ima, em, co, hit);
- hit->l = NULL;
- hit->luv = hit->luv_next = NULL;
+ hit.l = NULL;
+ hit.luv = hit.luv_next = NULL;
- mindist = 1e10f;
- memset(hit, 0, sizeof(*hit));
-
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMIter iter;
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
- continue;
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT);
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- if (penalty && uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
- dist = len_manhattan_v2v2(co, luv->uv) + len_manhattan_v2(penalty);
- else
- dist = len_manhattan_v2v2(co, luv->uv);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- if (dist <= mindist) {
- if (dist == mindist) {
- if (!uv_nearest_between(l, co, cd_loop_uv_offset)) {
- continue;
- }
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+
+ BMIter liter;
+ BMLoop *l;
+ int i;
+ BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
+ float dist_test_sq;
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ if (penalty_dist != 0.0f && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ dist_test_sq = len_v2v2(co, luv->uv) + penalty_dist;
+ dist_test_sq = SQUARE(dist_test_sq);
+ }
+ else {
+ dist_test_sq = len_squared_v2v2(co, luv->uv);
}
- mindist = dist;
+ if (dist_test_sq <= hit.dist_sq) {
+ if (dist_test_sq == hit.dist_sq) {
+ if (!uv_nearest_between(l, co, cd_loop_uv_offset)) {
+ continue;
+ }
+ }
- hit->l = l;
- hit->luv = luv;
- hit->luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
- hit->efa = efa;
- hit->lindex = i;
+ hit.dist_sq = dist_test_sq;
+
+ hit.l = l;
+ hit.luv = luv;
+ hit.luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
+ hit.efa = efa;
+ hit.lindex = i;
+ found = true;
+ }
}
}
}
+
+ if (found) {
+ *hit_final = hit;
+ }
+
+ return found;
}
bool ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, const float co[2], float r_uv[2])
@@ -842,7 +934,7 @@ bool ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, const float
copy_v2_v2(r_uv, co);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -861,7 +953,11 @@ bool ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, const float
return found;
}
-/*********************** loop select ***********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Loop Select
+ * \{ */
static void uv_select_edgeloop_vertex_loop_flag(UvMapVert *first)
{
@@ -946,8 +1042,9 @@ static bool uv_select_edgeloop_edge_tag_faces(BMEditMesh *em, UvMapVert *first1,
return true;
}
-static int uv_select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestHit *hit,
- const float limit[2], const bool extend)
+static int uv_select_edgeloop(
+ Scene *scene, Image *ima, Object *obedit, BMEditMesh *em, UvNearestHit *hit,
+ const float limit[2], const bool extend)
{
BMFace *efa;
BMIter iter, liter;
@@ -967,7 +1064,7 @@ static int uv_select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestH
BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
if (!extend) {
- uv_select_all_perform(scene, ima, em, SEL_DESELECT);
+ uv_select_all_perform(scene, ima, obedit, em, SEL_DESELECT);
}
BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
@@ -991,7 +1088,7 @@ static int uv_select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestH
/* find correct valence edges which are not tagged yet, but connect to tagged one */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && uvedit_face_visible_test(scene, ima, efa)) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && uvedit_face_visible_test(scene, obedit, ima, efa)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
/* check face not hidden and not tagged */
if (!(iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l)))
@@ -1044,9 +1141,15 @@ static int uv_select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestH
return (select) ? 1 : -1;
}
-/*********************** linked select ***********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Linked
+ * \{ */
-static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float limit[2], NearestHit *hit, bool extend, bool select_faces)
+static void uv_select_linked(
+ Scene *scene, Image *ima, Object *obedit, BMEditMesh *em, const float limit[2],
+ UvNearestHit *hit_final, bool extend, bool select_faces)
{
BMFace *efa;
BMLoop *l;
@@ -1076,9 +1179,10 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo
stack = MEM_mallocN(sizeof(*stack) * (em->bm->totface + 1), "UvLinkStack");
flag = MEM_callocN(sizeof(*flag) * em->bm->totface, "UvLinkFlag");
- if (!hit) {
+ if (hit_final == NULL) {
+ /* Use existing selection */
BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
- if (uvedit_face_visible_test(scene, ima, efa)) {
+ if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
if (select_faces) {
if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
stack[stacksize] = a;
@@ -1104,7 +1208,7 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo
}
else {
BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
- if (efa == hit->efa) {
+ if (efa == hit_final->efa) {
stack[stacksize] = a;
stacksize++;
flag[a] = 1;
@@ -1236,7 +1340,7 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo
/* WATCH IT: this returns first selected UV,
* not ideal in many cases since there could be multiple */
-static float *uv_sel_co_from_eve(Scene *scene, Image *ima, BMEditMesh *em, BMVert *eve)
+static float *uv_sel_co_from_eve(Scene *scene, Object *obedit, Image *ima, BMEditMesh *em, BMVert *eve)
{
BMIter liter;
BMLoop *l;
@@ -1244,7 +1348,7 @@ static float *uv_sel_co_from_eve(Scene *scene, Image *ima, BMEditMesh *em, BMVer
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) {
- if (!uvedit_face_visible_test(scene, ima, l->f))
+ if (!uvedit_face_visible_test(scene, obedit, ima, l->f))
continue;
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
@@ -1256,6 +1360,12 @@ static float *uv_sel_co_from_eve(Scene *scene, Image *ima, BMEditMesh *em, BMVer
return NULL;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select More/Less Operator
+ * \{ */
+
static int uv_select_more_less(bContext *C, const bool select)
{
Scene *scene = CTX_data_scene(C);
@@ -1286,13 +1396,11 @@ static int uv_select_more_less(bContext *C, const bool select)
if (ts->uv_selectmode == UV_SELECT_FACE) {
/* clear tags */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
- }
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
/* mark loops to be selected */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, ima, efa)) {
+ if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
#define IS_SEL 1
#define IS_UNSEL 2
@@ -1335,7 +1443,7 @@ static int uv_select_more_less(bContext *C, const bool select)
/* mark loops to be selected */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, ima, efa)) {
+ if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@@ -1393,7 +1501,11 @@ static void UV_OT_select_less(wmOperatorType *ot)
ot->poll = ED_operator_uvedit_space_image;
}
-/* ******************** align operator **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Weld Align Operator
+ * \{ */
static void uv_weld_align(bContext *C, int tool)
{
@@ -1418,7 +1530,7 @@ static void uv_weld_align(bContext *C, int tool)
BMLoop *l;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -1440,7 +1552,7 @@ static void uv_weld_align(bContext *C, int tool)
BMLoop *l;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -1459,7 +1571,7 @@ static void uv_weld_align(bContext *C, int tool)
BMLoop *l;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -1480,14 +1592,12 @@ static void uv_weld_align(bContext *C, int tool)
BMIter iter, liter, eiter;
/* clear tag */
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(eve, BM_ELEM_TAG);
- }
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
/* tag verts with a selected UV */
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) {
- if (!uvedit_face_visible_test(scene, ima, l->f))
+ if (!uvedit_face_visible_test(scene, obedit, ima, l->f))
continue;
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
@@ -1499,8 +1609,10 @@ static void uv_weld_align(bContext *C, int tool)
/* flush vertex tags to edges */
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_set(eed, BM_ELEM_TAG, (BM_elem_flag_test(eed->v1, BM_ELEM_TAG) &&
- BM_elem_flag_test(eed->v2, BM_ELEM_TAG)));
+ BM_elem_flag_set(
+ eed, BM_ELEM_TAG,
+ (BM_elem_flag_test(eed->v1, BM_ELEM_TAG) &&
+ BM_elem_flag_test(eed->v2, BM_ELEM_TAG)));
}
/* find a vertex with only one tagged edge */
@@ -1551,11 +1663,13 @@ static void uv_weld_align(bContext *C, int tool)
}
/* now we have all verts, make into a line */
- if (BLI_array_count(eve_line) > 2) {
+ if (BLI_array_len(eve_line) > 2) {
/* we know the returns from these must be valid */
- const float *uv_start = uv_sel_co_from_eve(scene, ima, em, eve_line[0]);
- const float *uv_end = uv_sel_co_from_eve(scene, ima, em, eve_line[BLI_array_count(eve_line) - 1]);
+ const float *uv_start = uv_sel_co_from_eve(
+ scene, obedit, ima, em, eve_line[0]);
+ const float *uv_end = uv_sel_co_from_eve(
+ scene, obedit, ima, em, eve_line[BLI_array_len(eve_line) - 1]);
/* For t & u modes */
float a = 0.0f;
@@ -1573,9 +1687,9 @@ static void uv_weld_align(bContext *C, int tool)
}
/* go over all verts except for endpoints */
- for (i = 0; i < BLI_array_count(eve_line); i++) {
+ for (i = 0; i < BLI_array_len(eve_line); i++) {
BM_ITER_ELEM (l, &liter, eve_line[i], BM_LOOPS_OF_VERT) {
- if (!uvedit_face_visible_test(scene, ima, l->f))
+ if (!uvedit_face_visible_test(scene, obedit, ima, l->f))
continue;
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
@@ -1644,7 +1758,12 @@ static void UV_OT_align(wmOperatorType *ot)
/* properties */
RNA_def_enum(ot->srna, "axis", axis_items, 'a', "Axis", "Axis to align UV locations on");
}
-/* ******************** weld near operator **************** */
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Remove Doubles Operator
+ * \{ */
typedef struct UVvert {
MLoopUV *uv_loop;
@@ -1682,9 +1801,9 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op)
MLoopUV **loop_arr = NULL;
BLI_array_declare(loop_arr);
- /* TODO, use qsort as with MESH_OT_remove_doubles, this isn't optimal */
+ /* TODO, use kd-tree as with MESH_OT_remove_doubles, this isn't optimal */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -1699,12 +1818,12 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op)
}
}
- for (uv_a_index = 0; uv_a_index < BLI_array_count(vert_arr); uv_a_index++) {
+ for (uv_a_index = 0; uv_a_index < BLI_array_len(vert_arr); uv_a_index++) {
if (vert_arr[uv_a_index].weld == false) {
float uv_min[2];
float uv_max[2];
- BLI_array_empty(loop_arr);
+ BLI_array_clear(loop_arr);
BLI_array_append(loop_arr, vert_arr[uv_a_index].uv_loop);
uv_a = vert_arr[uv_a_index].uv_loop->uv;
@@ -1713,7 +1832,7 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op)
copy_v2_v2(uv_min, uv_a);
vert_arr[uv_a_index].weld = true;
- for (uv_b_index = uv_a_index + 1; uv_b_index < BLI_array_count(vert_arr); uv_b_index++) {
+ for (uv_b_index = uv_a_index + 1; uv_b_index < BLI_array_len(vert_arr); uv_b_index++) {
uv_b = vert_arr[uv_b_index].uv_loop->uv;
if ((vert_arr[uv_b_index].weld == false) &&
(len_manhattan_v2v2(uv_a, uv_b) < threshold))
@@ -1723,10 +1842,10 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op)
vert_arr[uv_b_index].weld = true;
}
}
- if (BLI_array_count(loop_arr)) {
+ if (BLI_array_len(loop_arr)) {
float uv_mid[2];
mid_v2_v2v2(uv_mid, uv_min, uv_max);
- for (uv_b_index = 0; uv_b_index < BLI_array_count(loop_arr); uv_b_index++) {
+ for (uv_b_index = 0; uv_b_index < BLI_array_len(loop_arr); uv_b_index++) {
copy_v2_v2(loop_arr[uv_b_index]->uv, uv_mid);
}
}
@@ -1746,7 +1865,7 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op)
BLI_array_declare(loop_arr_unselected);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -1760,12 +1879,12 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op)
}
}
- for (uv_a_index = 0; uv_a_index < BLI_array_count(loop_arr); uv_a_index++) {
+ for (uv_a_index = 0; uv_a_index < BLI_array_len(loop_arr); uv_a_index++) {
float dist_best = FLT_MAX, dist;
const float *uv_best = NULL;
uv_a = loop_arr[uv_a_index]->uv;
- for (uv_b_index = 0; uv_b_index < BLI_array_count(loop_arr_unselected); uv_b_index++) {
+ for (uv_b_index = 0; uv_b_index < BLI_array_len(loop_arr_unselected); uv_b_index++) {
uv_b = loop_arr_unselected[uv_b_index]->uv;
dist = len_manhattan_v2v2(uv_a, uv_b);
if ((dist < threshold) && (dist < dist_best)) {
@@ -1805,7 +1924,12 @@ static void UV_OT_remove_doubles(wmOperatorType *ot)
"Merge Distance", "Maximum distance between welded vertices", 0.0f, 1.0f);
RNA_def_boolean(ot->srna, "use_unselected", 0, "Unselected", "Merge selected to other unselected vertices");
}
-/* ******************** weld operator **************** */
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Weld Near Operator
+ * \{ */
static int uv_weld_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -1827,10 +1951,13 @@ static void UV_OT_weld(wmOperatorType *ot)
ot->poll = ED_operator_uvedit;
}
+/** \} */
-/* ******************** (de)select all operator **************** */
+/* -------------------------------------------------------------------- */
+/** \name (De)Select All Operator
+ * \{ */
-static void uv_select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int action)
+static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, BMEditMesh *em, int action)
{
ToolSettings *ts = scene->toolsettings;
BMFace *efa;
@@ -1862,7 +1989,7 @@ static void uv_select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -1878,7 +2005,7 @@ static void uv_select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -1909,7 +2036,7 @@ static int uv_select_all_exec(bContext *C, wmOperator *op)
int action = RNA_enum_get(op->ptr, "action");
- uv_select_all_perform(scene, ima, em, action);
+ uv_select_all_perform(scene, ima, obedit, em, action);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
@@ -1931,9 +2058,13 @@ static void UV_OT_select_all(wmOperatorType *ot)
WM_operator_properties_select_all(ot);
}
-/* ******************** mouse select operator **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mouse Select Operator
+ * \{ */
-static bool uv_sticky_select(float *limit, int hitv[4], int v, float *hituv[4], float *uv, int sticky, int hitlen)
+static bool uv_sticky_select(float *limit, int hitv[], int v, float *hituv[], float *uv, int sticky, int hitlen)
{
int i;
@@ -1968,12 +2099,11 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
- NearestHit hit;
+ UvNearestHit hit = UV_NEAREST_HIT_INIT;
int i, selectmode, sticky, sync, *hitv = NULL;
bool select = true;
int flush = 0, hitlen = 0; /* 0 == don't flush, 1 == sel, -1 == desel; only use when selection sync is enabled */
float limit[2], **hituv = NULL;
- float penalty[2];
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
@@ -1983,8 +2113,13 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
* shift-selecting can consider an adjacent point close enough to add to
* the selection rather than de-selecting the closest. */
- uvedit_pixel_to_float(sima, limit, 0.05f);
- uvedit_pixel_to_float(sima, penalty, 5.0f / (sima ? sima->zoom : 1.0f));
+ float penalty_dist;
+ {
+ float penalty[2];
+ uvedit_pixel_to_float(sima, limit, 0.05f);
+ uvedit_pixel_to_float(sima, penalty, 5.0f / (sima ? sima->zoom : 1.0f));
+ penalty_dist = len_v2(penalty);
+ }
/* retrieve operation mode */
if (ts->uv_flag & UV_SYNC_SELECTION) {
@@ -2008,8 +2143,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
/* find nearest element */
if (loop) {
/* find edge */
- uv_find_nearest_edge(scene, ima, em, co, &hit);
- if (hit.efa == NULL) {
+ if (!uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
return OPERATOR_CANCELLED;
}
@@ -2017,8 +2151,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
}
else if (selectmode == UV_SELECT_VERTEX) {
/* find vertex */
- uv_find_nearest_vert(scene, ima, em, co, penalty, &hit);
- if (hit.efa == NULL) {
+ if (!uv_find_nearest_vert(scene, ima, obedit, co, penalty_dist, &hit)) {
return OPERATOR_CANCELLED;
}
@@ -2034,8 +2167,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
}
else if (selectmode == UV_SELECT_EDGE) {
/* find edge */
- uv_find_nearest_edge(scene, ima, em, co, &hit);
- if (hit.efa == NULL) {
+ if (!uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
return OPERATOR_CANCELLED;
}
@@ -2053,11 +2185,10 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
}
else if (selectmode == UV_SELECT_FACE) {
/* find face */
- uv_find_nearest_face(scene, ima, em, co, &hit);
- if (hit.efa == NULL) {
+ if (!uv_find_nearest_face(scene, ima, obedit, co, &hit)) {
return OPERATOR_CANCELLED;
}
-
+
/* make active */
BM_mesh_active_face_set(em->bm, hit.efa);
@@ -2074,9 +2205,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
hitlen = hit.efa->len;
}
else if (selectmode == UV_SELECT_ISLAND) {
- uv_find_nearest_edge(scene, ima, em, co, &hit);
-
- if (hit.efa == NULL) {
+ if (!uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
return OPERATOR_CANCELLED;
}
@@ -2089,10 +2218,10 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
/* do selection */
if (loop) {
- flush = uv_select_edgeloop(scene, ima, em, &hit, limit, extend);
+ flush = uv_select_edgeloop(scene, ima, obedit, em, &hit, limit, extend);
}
else if (selectmode == UV_SELECT_ISLAND) {
- uv_select_linked(scene, ima, em, limit, &hit, extend, false);
+ uv_select_linked(scene, ima, obedit, em, limit, &hit, extend, false);
}
else if (extend) {
if (selectmode == UV_SELECT_VERTEX) {
@@ -2127,7 +2256,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -2142,7 +2271,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
}
else {
/* deselect all */
- uv_select_all_perform(scene, ima, em, SEL_DESELECT);
+ uv_select_all_perform(scene, ima, obedit, em, SEL_DESELECT);
if (selectmode == UV_SELECT_VERTEX) {
/* select vertex */
@@ -2162,7 +2291,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
/* select sticky uvs */
if (sticky != SI_STICKY_DISABLE) {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -2254,7 +2383,11 @@ static void UV_OT_select(wmOperatorType *ot)
"Location", "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds", -100.0f, 100.0f);
}
-/* ******************** loop select operator **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Loop Select Operator
+ * \{ */
static int uv_select_loop_exec(bContext *C, wmOperator *op)
{
@@ -2299,7 +2432,11 @@ static void UV_OT_select_loop(wmOperatorType *ot)
"Location", "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds", -100.0f, 100.0f);
}
-/* ******************** linked select operator **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Linked Operator
+ * \{ */
static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent *event, int pick)
{
@@ -2313,7 +2450,7 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent
int extend;
bool select_faces = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE);
- NearestHit hit, *hit_p = NULL;
+ UvNearestHit hit = UV_NEAREST_HIT_INIT;
if ((ts->uv_flag & UV_SYNC_SELECTION) && !(ts->selectmode & SCE_SELECT_FACE)) {
BKE_report(op->reports, RPT_ERROR, "Select linked only works in face select mode when sync selection is enabled");
@@ -2338,11 +2475,12 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent
RNA_float_get_array(op->ptr, "location", co);
}
- uv_find_nearest_edge(scene, ima, em, co, &hit);
- hit_p = &hit;
+ if (!uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
+ return OPERATOR_CANCELLED;
+ }
}
- uv_select_linked(scene, ima, em, limit, hit_p, extend, select_faces);
+ uv_select_linked(scene, ima, obedit, em, limit, pick ? &hit : NULL, extend, select_faces);
DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
@@ -2434,7 +2572,7 @@ static int uv_select_split_exec(bContext *C, wmOperator *op)
bool is_sel = false;
bool is_unsel = false;
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
/* are we all selected? */
@@ -2506,17 +2644,21 @@ static void uv_select_sync_flush(ToolSettings *ts, BMEditMesh *em, const short s
}
}
-
+/** \} */
/* -------------------------------------------------------------------- */
-/* Utility functions to flush the uv-selection from tags */
+/** \name Select/Tag Flushing Utils
+ *
+ * Utility functions to flush the uv-selection from tags.
+ * \{ */
/**
* helper function for #uv_select_flush_from_tag_loop and uv_select_flush_from_tag_face
*/
-static void uv_select_flush_from_tag_sticky_loc_internal(Scene *scene, BMEditMesh *em, UvVertMap *vmap,
- const unsigned int efa_index, BMLoop *l,
- const bool select, const int cd_loop_uv_offset)
+static void uv_select_flush_from_tag_sticky_loc_internal(
+ Scene *scene, BMEditMesh *em, UvVertMap *vmap,
+ const unsigned int efa_index, BMLoop *l,
+ const bool select, const int cd_loop_uv_offset)
{
UvMapVert *start_vlist = NULL, *vlist_iter;
BMFace *efa_vlist;
@@ -2580,12 +2722,8 @@ static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object
if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) {
/* Tag all verts as untouched, then touch the ones that have a face center
* in the loop and select all MLoopUV's that use a touched vert. */
- BMVert *eve;
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(eve, BM_ELEM_TAG);
- }
-
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -2623,8 +2761,9 @@ static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object
/* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- uv_select_flush_from_tag_sticky_loc_internal(scene, em, vmap, efa_index, l,
- select, cd_loop_uv_offset);
+ uv_select_flush_from_tag_sticky_loc_internal(
+ scene, em, vmap, efa_index, l,
+ select, cd_loop_uv_offset);
}
}
}
@@ -2670,11 +2809,7 @@ static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object
if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) {
/* Tag all verts as untouched, then touch the ones that have a face center
* in the loop and select all MLoopUV's that use a touched vert. */
- BMVert *eve;
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(eve, BM_ELEM_TAG);
- }
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -2713,8 +2848,9 @@ static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l, BM_ELEM_TAG)) {
- uv_select_flush_from_tag_sticky_loc_internal(scene, em, vmap, efa_index, l,
- select, cd_loop_uv_offset);
+ uv_select_flush_from_tag_sticky_loc_internal(
+ scene, em, vmap, efa_index, l,
+ select, cd_loop_uv_offset);
}
}
}
@@ -2732,7 +2868,11 @@ static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object
}
}
-/* ******************** border select operator **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Border Select Operator
+ * \{ */
static int uv_border_select_exec(bContext *C, wmOperator *op)
{
@@ -2749,9 +2889,10 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
MLoopUV *luv;
rctf rectf;
bool changed, pinned, select, extend;
- const bool use_face_center = (ts->uv_flag & UV_SYNC_SELECTION) ?
- (ts->selectmode == SCE_SELECT_FACE) :
- (ts->uv_selectmode == UV_SELECT_FACE);
+ const bool use_face_center = (
+ (ts->uv_flag & UV_SYNC_SELECTION) ?
+ (ts->selectmode == SCE_SELECT_FACE) :
+ (ts->uv_selectmode == UV_SELECT_FACE));
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
@@ -2765,7 +2906,7 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
pinned = RNA_boolean_get(op->ptr, "pinned");
if (!extend)
- uv_select_all_perform(scene, ima, em, SEL_DESELECT);
+ uv_select_all_perform(scene, ima, obedit, em, SEL_DESELECT);
/* do actual selection */
if (use_face_center && !pinned) {
@@ -2778,7 +2919,7 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
/* assume not touched */
BM_elem_flag_disable(efa, BM_ELEM_TAG);
- if (uvedit_face_visible_test(scene, ima, efa)) {
+ if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
uv_poly_center(efa, cent, cd_loop_uv_offset);
if (BLI_rctf_isect_pt_v(&rectf, cent)) {
BM_elem_flag_enable(efa, BM_ELEM_TAG);
@@ -2795,9 +2936,10 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
else {
/* other selection modes */
changed = true;
-
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@@ -2807,15 +2949,21 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
/* UV_SYNC_SELECTION - can't do pinned selection */
if (BLI_rctf_isect_pt_v(&rectf, luv->uv)) {
uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
}
}
else if (pinned) {
if ((luv->flag & MLOOPUV_PINNED) && BLI_rctf_isect_pt_v(&rectf, luv->uv)) {
uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
}
}
}
}
+
+ if (sima->sticky == SI_STICKY_VERTEX) {
+ uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
+ }
}
if (changed) {
@@ -2854,7 +3002,11 @@ static void UV_OT_select_border(wmOperatorType *ot)
WM_operator_properties_gesture_border_select(ot);
}
-/* ******************** circle select operator **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Circle Select Operator
+ * \{ */
static int uv_inside_circle(const float uv[2], const float offset[2], const float ellipse[2])
{
@@ -2865,19 +3017,6 @@ static int uv_inside_circle(const float uv[2], const float offset[2], const floa
return ((x * x + y * y) < 1.0f);
}
-static bool uv_select_inside_ellipse(BMEditMesh *em, Scene *scene, const bool select,
- const float offset[2], const float ellipse[2], BMLoop *l, MLoopUV *luv,
- const int cd_loop_uv_offset)
-{
- if (uv_inside_circle(luv->uv, offset, ellipse)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- return true;
- }
- else {
- return false;
- }
-}
-
static int uv_circle_select_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima = CTX_wm_space_image(C);
@@ -2894,9 +3033,10 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
float zoomx, zoomy, offset[2], ellipse[2];
const bool select = !RNA_boolean_get(op->ptr, "deselect");
bool changed = false;
- const bool use_face_center = (ts->uv_flag & UV_SYNC_SELECTION) ?
- (ts->selectmode == SCE_SELECT_FACE) :
- (ts->uv_selectmode == UV_SELECT_FACE);
+ const bool use_face_center = (
+ (ts->uv_flag & UV_SYNC_SELECTION) ?
+ (ts->selectmode == SCE_SELECT_FACE) :
+ (ts->uv_selectmode == UV_SELECT_FACE));
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
@@ -2937,12 +3077,22 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
}
}
else {
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- changed |= uv_select_inside_ellipse(em, scene, select, offset, ellipse, l, luv, cd_loop_uv_offset);
+ if (uv_inside_circle(luv->uv, offset, ellipse)) {
+ changed = true;
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ }
}
}
+
+ if (sima->sticky == SI_STICKY_VERTEX) {
+ uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
+ }
}
if (changed) {
@@ -2975,11 +3125,15 @@ static void UV_OT_circle_select(wmOperatorType *ot)
WM_operator_properties_gesture_circle_select(ot);
}
+/** \} */
-/* ******************** lasso select operator **************** */
+/* -------------------------------------------------------------------- */
+/** \name Lasso Select Operator
+ * \{ */
-static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short moves,
- const bool select, const bool extend)
+static bool do_lasso_select_mesh_uv(
+ bContext *C, const int mcords[][2], short moves,
+ const bool select, const bool extend)
{
SpaceImage *sima = CTX_wm_space_image(C);
Image *ima = CTX_data_edit_image(C);
@@ -3006,7 +3160,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo
BLI_lasso_boundbox(&rect, mcords, moves);
if (!extend && select) {
- uv_select_all_perform(scene, ima, em, SEL_DESELECT);
+ uv_select_all_perform(scene, ima, obedit, em, SEL_DESELECT);
}
if (use_face_center) { /* Face Center Sel */
@@ -3033,24 +3187,32 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo
}
}
else { /* Vert Sel */
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, ima, efa)) {
+ if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- if (UI_view2d_view_to_region_clip(&ar->v2d,
- luv->uv[0], luv->uv[1],
- &screen_uv[0], &screen_uv[1]) &&
+ if (UI_view2d_view_to_region_clip(
+ &ar->v2d,
+ luv->uv[0], luv->uv[1],
+ &screen_uv[0], &screen_uv[1]) &&
BLI_rcti_isect_pt_v(&rect, screen_uv) &&
BLI_lasso_is_point_inside(mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED))
{
uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
changed = true;
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
}
}
}
}
}
+
+ if (sima->sticky == SI_STICKY_VERTEX) {
+ uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
+ }
}
if (changed) {
@@ -3104,9 +3266,11 @@ static void UV_OT_select_lasso(wmOperatorType *ot)
WM_operator_properties_gesture_lasso_select(ot);
}
+/** \} */
-
-/* ******************** snap cursor operator **************** */
+/* -------------------------------------------------------------------- */
+/** \name Snap Cursor Operator
+ * \{ */
static void uv_snap_to_pixel(float uvco[2], float w, float h)
{
@@ -3174,7 +3338,11 @@ static void UV_OT_snap_cursor(wmOperatorType *ot)
RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UVs to");
}
-/* ******************** snap selection operator **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Snap Selection Operator
+ * \{ */
static bool uv_snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, const float cursor[2])
{
@@ -3188,7 +3356,7 @@ static bool uv_snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, cons
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -3215,7 +3383,7 @@ static bool uv_snap_uvs_offset(Scene *scene, Image *ima, Object *obedit, const f
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -3244,7 +3412,7 @@ static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object
/* index every vert that has a selected UV using it, but only once so as to
* get unique indices and to count how much to malloc */
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, ima, f)) {
+ if (uvedit_face_visible_test(scene, obedit, ima, f)) {
BM_elem_flag_enable(f, BM_ELEM_TAG);
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
BM_elem_flag_set(l, BM_ELEM_TAG, uvedit_uv_select_test(scene, l, cd_loop_uv_offset));
@@ -3304,7 +3472,7 @@ static bool uv_snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit
h = (float)height;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -3383,7 +3551,11 @@ static void UV_OT_snap_selected(wmOperatorType *ot)
RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UVs to");
}
-/* ******************** pin operator **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Pin UV's Operator
+ * \{ */
static int uv_pin_exec(bContext *C, wmOperator *op)
{
@@ -3400,7 +3572,7 @@ static int uv_pin_exec(bContext *C, wmOperator *op)
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -3438,7 +3610,11 @@ static void UV_OT_pin(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear pinning for the selection instead of setting it");
}
-/******************* select pinned operator ***************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Pinned UV's Operator
+ * \{ */
static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -3454,7 +3630,7 @@ static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op))
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, ima, efa))
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -3483,15 +3659,20 @@ static void UV_OT_select_pinned(wmOperatorType *ot)
ot->poll = ED_operator_uvedit;
}
-/********************** hide operator *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Hide Operator
+ * \{ */
/* check if we are selected or unselected based on 'bool_test' arg,
* needed for select swap support */
#define UV_SEL_TEST(luv, bool_test) ((((luv)->flag & MLOOPUV_VERTSEL) == MLOOPUV_VERTSEL) == bool_test)
/* is every UV vert selected or unselected depending on bool_test */
-static bool bm_face_is_all_uv_sel(BMFace *f, bool select_test,
- const int cd_loop_uv_offset)
+static bool bm_face_is_all_uv_sel(
+ BMFace *f, bool select_test,
+ const int cd_loop_uv_offset)
{
BMLoop *l_iter;
BMLoop *l_first;
@@ -3534,7 +3715,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
int hide = 0;
- if (!uvedit_face_visible_test(scene, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
continue;
}
@@ -3617,7 +3798,11 @@ static void UV_OT_hide(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
}
-/****************** reveal operator ******************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Reveal Operator
+ * \{ */
static int uv_reveal_exec(bContext *C, wmOperator *op)
{
@@ -3752,7 +3937,11 @@ static void UV_OT_reveal(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
-/******************** set 3d cursor operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set 2D Cursor Operator
+ * \{ */
static int uv_set_2d_cursor_poll(bContext *C)
{
@@ -3815,6 +4004,12 @@ static void UV_OT_cursor_set(wmOperatorType *ot)
"Cursor location in normalized (0.0-1.0) coordinates", -10.0f, 10.0f);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Seam from UV Islands Operator
+ * \{ */
+
static int uv_seams_from_islands_exec(bContext *C, wmOperator *op)
{
UvVertMap *vmap;
@@ -3949,6 +4144,12 @@ static void UV_OT_seams_from_islands(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "mark_sharp", 0, "Mark Sharp", "Mark boundary edges as sharp");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mark Seam Operator
+ * \{ */
+
static int uv_mark_seam_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_edit_object(C);
@@ -3959,17 +4160,14 @@ static int uv_mark_seam_exec(bContext *C, wmOperator *op)
BMFace *efa;
BMLoop *loop;
BMIter iter, liter;
- bool clear = RNA_boolean_get(op->ptr, "clear");
+ bool flag_set = !RNA_boolean_get(op->ptr, "clear");
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_edge_select_test(scene, loop, cd_loop_uv_offset)) {
- if (clear)
- BM_elem_flag_disable(loop->e, BM_ELEM_SEAM);
- else
- BM_elem_flag_enable(loop->e, BM_ELEM_SEAM);
+ BM_elem_flag_set(loop->e, BM_ELEM_SEAM, flag_set);
}
}
}
@@ -4024,8 +4222,11 @@ static void UV_OT_mark_seam(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "clear", false, "Clear Seams", "Clear instead of marking seams");
}
+/** \} */
-/* ************************** registration **********************************/
+/* -------------------------------------------------------------------- */
+/** \name Operator Registration & Keymap
+ * \{ */
void ED_operatortypes_uvedit(void)
{
@@ -4159,3 +4360,4 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf)
transform_keymap_for_space(keyconf, keymap, SPACE_IMAGE);
}
+/** \} */
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index 29c908ff900..c510c12ae53 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -32,8 +32,8 @@
#include "BLI_math.h"
#include "BLI_rand.h"
#include "BLI_heap.h"
-#include "BLI_boxpack2d.h"
-#include "BLI_convexhull2d.h"
+#include "BLI_boxpack_2d.h"
+#include "BLI_convexhull_2d.h"
#include "uvedit_parametrizer.h"
@@ -1291,7 +1291,7 @@ static void p_chart_fill_boundary(PChart *chart, PEdge *be, int nedges)
while (nedges > 2) {
PEdge *ne, *ne1, *ne2;
- e = (PEdge *)BLI_heap_popmin(heap);
+ e = (PEdge *)BLI_heap_pop_min(heap);
e1 = p_boundary_edge_prev(e);
e2 = p_boundary_edge_next(e);
@@ -2185,12 +2185,12 @@ static void p_chart_simplify_compute(PChart *chart)
e->u.nextcollapse = NULL;
/* pop edge collapse out of heap one by one */
- while (!BLI_heap_empty(heap)) {
+ while (!BLI_heap_is_empty(heap)) {
if (ncollapsed == NCOLLAPSE)
break;
HeapNode *link = BLI_heap_top(heap);
- PEdge *edge = (PEdge *)BLI_heap_popmin(heap), *pair = edge->pair;
+ PEdge *edge = (PEdge *)BLI_heap_pop_min(heap), *pair = edge->pair;
PVert *oldv, *keepv;
PEdge *wheele, *nexte;
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index fa936e998fa..4c205818329 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -157,6 +157,8 @@ typedef struct StitchState {
bool snap_islands;
/* stitch at midpoints or at islands */
bool midpoints;
+ /* object for editmesh */
+ Object *obedit;
/* editmesh, cached for use in modal handler */
BMEditMesh *em;
/* clear seams of stitched edges after stitch */
@@ -1719,6 +1721,7 @@ static int stitch_init(bContext *C, wmOperator *op)
/* initialize state */
state->use_limit = RNA_boolean_get(op->ptr, "use_limit");
state->limit_dist = RNA_float_get(op->ptr, "limit");
+ state->obedit = obedit;
state->em = em;
state->snap_islands = RNA_boolean_get(op->ptr, "snap_islands");
state->static_island = RNA_int_get(op->ptr, "static_island");
@@ -1848,7 +1851,7 @@ static int stitch_init(bContext *C, wmOperator *op)
}
}
- total_edges = BLI_ghash_size(edge_hash);
+ total_edges = BLI_ghash_len(edge_hash);
state->edges = edges = MEM_mallocN(sizeof(*edges) * total_edges, "stitch_edges");
/* I assume any system will be able to at least allocate an iterator :p */
@@ -2124,16 +2127,16 @@ static void stitch_select(bContext *C, Scene *scene, const wmEvent *event, Stitc
{
/* add uv under mouse to processed uv's */
float co[2];
- NearestHit hit;
+ UvNearestHit hit = UV_NEAREST_HIT_INIT;
ARegion *ar = CTX_wm_region(C);
Image *ima = CTX_data_edit_image(C);
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
if (state->mode == STITCH_VERT) {
- uv_find_nearest_vert(scene, ima, state->em, co, NULL, &hit);
-
- if (hit.efa) {
+ if (uv_find_nearest_vert(
+ scene, ima, state->obedit, co, 0.0f, &hit))
+ {
/* Add vertex to selection, deselect all common uv's of vert other
* than selected and update the preview. This behavior was decided so that
* you can do stuff like deselect the opposite stitchable vertex and the initial still gets deselected */
@@ -2145,9 +2148,9 @@ static void stitch_select(bContext *C, Scene *scene, const wmEvent *event, Stitc
}
}
else {
- uv_find_nearest_edge(scene, ima, state->em, co, &hit);
-
- if (hit.efa) {
+ if (uv_find_nearest_edge(
+ scene, ima, state->obedit, co, &hit))
+ {
UvEdge *edge = uv_edge_get(hit.l, state);
stitch_select_edge(edge, state, false);
}
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
index a0da68849f7..c1fa86d4653 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
@@ -52,8 +52,6 @@ BlenderFileLoader::~BlenderFileLoader()
NodeGroup *BlenderFileLoader::Load()
{
- ObjectInstanceRen *obi;
-
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "\n=== Importing triangular meshes into Blender ===" << endl;
}
@@ -81,6 +79,19 @@ NodeGroup *BlenderFileLoader::Load()
_z_offset = 0.f;
}
+ ViewLayer *view_layer = (ViewLayer*)BLI_findstring(&_re->scene->view_layers, _view_layer->name, offsetof(ViewLayer, name));
+
+ EvaluationContext *eval_ctx = DEG_evaluation_context_new(DAG_EVAL_RENDER);
+ Depsgraph *depsgraph = DEG_graph_new(_re->scene, view_layer, DAG_EVAL_RENDER);
+
+ DEG_evaluation_context_init_from_view_layer_for_render(
+ eval_ctx,
+ depsgraph,
+ _re->scene,
+ view_layer);
+
+ BKE_scene_graph_update_tagged(depsgraph, _re->main);
+
#if 0
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Frustum: l " << _viewplane_left << " r " << _viewplane_right
@@ -90,32 +101,38 @@ NodeGroup *BlenderFileLoader::Load()
#endif
int id = 0;
- unsigned cnt = 1;
- unsigned cntStep = (unsigned)ceil(0.01f * _re->totinstance);
- for (obi = (ObjectInstanceRen *)_re->instancetable.first; obi; obi = obi->next) {
- if (_pRenderMonitor) {
- if (_pRenderMonitor->testBreak())
- break;
- if (cnt % cntStep == 0) {
- stringstream ss;
- ss << "Freestyle: Mesh loading " << (100 * cnt / _re->totinstance) << "%";
- _pRenderMonitor->setInfo(ss.str());
- _pRenderMonitor->progress((float)cnt / _re->totinstance);
- }
- cnt++;
+
+ DEG_OBJECT_ITER_BEGIN(
+ depsgraph, ob, DEG_ITER_OBJECT_MODE_RENDER,
+ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
+ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET |
+ DEG_ITER_OBJECT_FLAG_VISIBLE |
+ DEG_ITER_OBJECT_FLAG_DUPLI)
+ {
+ if (_pRenderMonitor && _pRenderMonitor->testBreak()) {
+ break;
}
- char *name = obi->ob->id.name;
- //printf("%c%c:%s\n", name[0], name[1], name+2);
- //print_m4("obi->mat", obi->mat);
+ bool apply_modifiers = true;
+ bool calc_undeformed = false;
+ bool calc_tessface = false;
+ Mesh *mesh = BKE_mesh_new_from_object(eval_ctx,
+ _re->main,
+ _re->scene,
+ ob,
+ apply_modifiers,
+ calc_tessface,
+ calc_undeformed);
- if (obi->obr->totvlak > 0) {
- insertShapeNode(obi, ++id);
- }
- else if (G.debug & G_DEBUG_FREESTYLE) {
- cout << "Warning: " << (name + 2) << " is not a vlak-based object (ignored)" << endl;
+ if (mesh) {
+ insertShapeNode(ob, mesh, ++id);
+ BKE_libblock_free_ex(_re->main, &mesh->id, true, false);
}
}
+ DEG_OBJECT_ITER_END;
+
+ DEG_graph_free(depsgraph);
+ DEG_evaluation_context_free(eval_ctx);
// Return the built scene.
return _Scene;
@@ -363,82 +380,87 @@ int BlenderFileLoader::testDegenerateTriangle(float v1[3], float v2[3], float v3
return 0;
}
-// Checks if edge rotation (if necessary) can prevent the given quad from
-// being decomposed into a degenerate triangle
-bool BlenderFileLoader::testEdgeRotation(float v1[3], float v2[3], float v3[3], float v4[3])
+static bool testEdgeMark(Mesh *me, FreestyleEdge *fed, const MLoopTri *lt, int i)
{
- if (testDegenerateTriangle(v1, v2, v3) == 2 || testDegenerateTriangle(v1, v3, v4) == 2) {
- if (testDegenerateTriangle(v1, v2, v4) == 2 || testDegenerateTriangle(v2, v3, v4) == 2) {
-#if 0
- if (G.debug & G_DEBUG_FREESTYLE) {
- printf("BlenderFileLoader::testEdgeRotation: edge rotation is unsuccessful.\n");
- }
-#endif
- return false;
- }
- return true;
+ MLoop *mloop = &me->mloop[lt->tri[i]];
+ MLoop *mloop_next = &me->mloop[lt->tri[(i+1)%3]];
+ MEdge *medge = &me->medge[mloop->e];
+
+ if (!ELEM(mloop_next->v, medge->v1, medge->v2)) {
+ /* Not an edge in the original mesh before triangulation. */
+ return false;
}
- return false;
+
+ return (fed[mloop->e].flag & FREESTYLE_EDGE_MARK) != 0;
}
-void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
+void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id)
{
- ObjectRen *obr = obi->obr;
- char *name = obi->ob->id.name + 2;
+ char *name = ob->id.name + 2;
+
+ // Compute loop triangles
+ int tottri = poly_to_tri_count(me->totpoly, me->totloop);
+ MLoopTri *mlooptri = (MLoopTri*)MEM_malloc_arrayN(tottri, sizeof(*mlooptri), __func__);
+ BKE_mesh_recalc_looptri(
+ me->mloop, me->mpoly,
+ me->mvert,
+ me->totloop, me->totpoly,
+ mlooptri);
+
+ // Compute loop normals
+ BKE_mesh_calc_normals_split(me);
+ float (*lnors)[3] = NULL;
+
+ if (CustomData_has_layer(&me->ldata, CD_NORMAL)) {
+ lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL);
+ }
- // We parse vlak nodes and count the number of faces after the clipping by
- // the near and far view planes is applied (Note: mesh vertices are in the
- // camera coordinate system).
- VlakRen *vlr = NULL;
+ // Get other mesh data
+ MVert *mvert = me->mvert;
+ MLoop *mloop = me->mloop;
+ MPoly *mpoly = me->mpoly;
+ FreestyleEdge *fed = (FreestyleEdge*)CustomData_get_layer(&me->edata, CD_FREESTYLE_EDGE);
+ FreestyleFace *ffa = (FreestyleFace*)CustomData_get_layer(&me->pdata, CD_FREESTYLE_FACE);
+
+ // Compute matrix including camera transform
+ float obmat[4][4], nmat[4][4];
+ mul_m4_m4m4(obmat, _re->viewmat, ob->obmat);
+ invert_m4_m4(nmat, obmat);
+ transpose_m4(nmat);
+
+ // We count the number of triangles after the clipping by the near and far view
+ // planes is applied (Note: mesh vertices are in the camera coordinate system).
unsigned numFaces = 0;
- float v1[3], v2[3], v3[3], v4[3];
- float n1[3], n2[3], n3[3], n4[3], facenormal[3];
- int clip_1[3], clip_2[3];
+ float v1[3], v2[3], v3[3];
+ float n1[3], n2[3], n3[3], facenormal[3];
+ int clip[3];
int wire_material = 0;
- for (int a = 0; a < obr->totvlak; a++) {
- if ((a & 255) == 0)
- vlr = obr->vlaknodes[a>>8].vlak;
- else
- vlr++;
- if (vlr->mat->mode & MA_ONLYCAST)
+ for (int a = 0; a < tottri; a++) {
+ const MLoopTri *lt = &mlooptri[a];
+ const MPoly *mp = &mpoly[lt->poly];
+ Material *mat = give_current_material(ob, mp->mat_nr + 1);
+
+ if (mat && mat->mode & MA_ONLYCAST) {
continue;
- if (vlr->mat->material_type == MA_TYPE_WIRE) {
+ }
+ if (mat && mat->material_type == MA_TYPE_WIRE) {
wire_material = 1;
continue;
}
- copy_v3_v3(v1, vlr->v1->co);
- copy_v3_v3(v2, vlr->v2->co);
- copy_v3_v3(v3, vlr->v3->co);
- if (vlr->v4)
- copy_v3_v3(v4, vlr->v4->co);
- if (obi->flag & R_TRANSFORMED) {
- mul_m4_v3(obi->mat, v1);
- mul_m4_v3(obi->mat, v2);
- mul_m4_v3(obi->mat, v3);
- if (vlr->v4)
- mul_m4_v3(obi->mat, v4);
- }
+
+ copy_v3_v3(v1, mvert[mloop[lt->tri[0]].v].co);
+ copy_v3_v3(v2, mvert[mloop[lt->tri[1]].v].co);
+ copy_v3_v3(v3, mvert[mloop[lt->tri[2]].v].co);
+
+ mul_m4_v3(obmat, v1);
+ mul_m4_v3(obmat, v2);
+ mul_m4_v3(obmat, v3);
+
v1[2] += _z_offset;
v2[2] += _z_offset;
v3[2] += _z_offset;
- if (vlr->v4)
- v4[2] += _z_offset;
-#if 0
- print_v3("v1", v1);
- print_v3("v2", v2);
- print_v3("v3", v3);
- if (vlr->v4)
- print_v3("v4", v4);
-#endif
- if (!vlr->v4 || !testEdgeRotation(v1, v2, v3, v4)) {
- numFaces += countClippedFaces(v1, v2, v3, clip_1);
- if (vlr->v4)
- numFaces += countClippedFaces(v1, v3, v4, clip_2);
- }
- else {
- numFaces += countClippedFaces(v1, v2, v4, clip_1);
- numFaces += countClippedFaces(v2, v3, v4, clip_2);
- }
+
+ numFaces += countClippedFaces(v1, v2, v3, clip);
}
if (wire_material) {
if (G.debug & G_DEBUG_FREESTYLE) {
@@ -450,8 +472,10 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
cout << "numFaces " << numFaces << endl;
}
#endif
- if (numFaces == 0)
+ if (numFaces == 0) {
+ MEM_freeN(mlooptri);
return;
+ }
// We allocate memory for the meshes to be imported
NodeGroup *currentMesh = new NodeGroup;
@@ -494,99 +518,60 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
// We parse the vlak nodes again and import meshes while applying the clipping
// by the near and far view planes.
- int p;
- for (p = 0; p < obr->totvlak; ++p) { // we parse the faces of the mesh
- if ((p & 255) == 0)
- vlr = obr->vlaknodes[p>>8].vlak;
- else
- vlr++;
- if ((vlr->mat->mode & MA_ONLYCAST) || vlr->mat->material_type == MA_TYPE_WIRE)
+ for (int a = 0; a < tottri; a++) {
+ const MLoopTri *lt = &mlooptri[a];
+ const MPoly *mp = &mpoly[lt->poly];
+ Material *mat = give_current_material(ob, mp->mat_nr + 1);
+
+ if (mat && ((mat->mode & MA_ONLYCAST) || mat->material_type == MA_TYPE_WIRE))
continue;
- copy_v3_v3(v1, vlr->v1->co);
- copy_v3_v3(v2, vlr->v2->co);
- copy_v3_v3(v3, vlr->v3->co);
- if (vlr->v4)
- copy_v3_v3(v4, vlr->v4->co);
- if (obi->flag & R_TRANSFORMED) {
- mul_m4_v3(obi->mat, v1);
- mul_m4_v3(obi->mat, v2);
- mul_m4_v3(obi->mat, v3);
- if (vlr->v4)
- mul_m4_v3(obi->mat, v4);
- }
+
+ copy_v3_v3(v1, mvert[mloop[lt->tri[0]].v].co);
+ copy_v3_v3(v2, mvert[mloop[lt->tri[1]].v].co);
+ copy_v3_v3(v3, mvert[mloop[lt->tri[2]].v].co);
+
+ mul_m4_v3(obmat, v1);
+ mul_m4_v3(obmat, v2);
+ mul_m4_v3(obmat, v3);
+
v1[2] += _z_offset;
v2[2] += _z_offset;
v3[2] += _z_offset;
- if (vlr->v4)
- v4[2] += _z_offset;
- if (_smooth && (vlr->flag & R_SMOOTH)) {
- copy_v3_v3(n1, vlr->v1->n);
- copy_v3_v3(n2, vlr->v2->n);
- copy_v3_v3(n3, vlr->v3->n);
- if (vlr->v4)
- copy_v3_v3(n4, vlr->v4->n);
- if (obi->flag & R_TRANSFORMED) {
- mul_m3_v3(obi->nmat, n1);
- mul_m3_v3(obi->nmat, n2);
- mul_m3_v3(obi->nmat, n3);
- normalize_v3(n1);
- normalize_v3(n2);
- normalize_v3(n3);
- if (vlr->v4) {
- mul_m3_v3(obi->nmat, n4);
- normalize_v3(n4);
- }
- }
+
+ if (_smooth && (mp->flag & ME_SMOOTH) && lnors) {
+ copy_v3_v3(n1, lnors[lt->tri[0]]);
+ copy_v3_v3(n2, lnors[lt->tri[1]]);
+ copy_v3_v3(n3, lnors[lt->tri[2]]);
+
+ mul_mat3_m4_v3(nmat, n1);
+ mul_mat3_m4_v3(nmat, n2);
+ mul_mat3_m4_v3(nmat, n3);
+
+ normalize_v3(n1);
+ normalize_v3(n2);
+ normalize_v3(n3);
}
else {
- RE_vlakren_get_normal(_re, obi, vlr, facenormal);
-#ifndef NDEBUG
- /* test if normals are inverted in rendering [T39669] */
- float tnor[3];
- if (vlr->v4)
- normal_quad_v3(tnor, v4, v3, v2, v1);
- else
- normal_tri_v3(tnor, v3, v2, v1);
- BLI_assert(dot_v3v3(tnor, facenormal) > 0.0f);
-#endif
+ normal_tri_v3(facenormal, v3, v2, v1);
+
copy_v3_v3(n1, facenormal);
copy_v3_v3(n2, facenormal);
copy_v3_v3(n3, facenormal);
- if (vlr->v4)
- copy_v3_v3(n4, facenormal);
}
- unsigned int numTris_1, numTris_2;
- bool edge_rotation;
- if (!vlr->v4 || !testEdgeRotation(v1, v2, v3, v4)) {
- numTris_1 = countClippedFaces(v1, v2, v3, clip_1);
- numTris_2 = (!vlr->v4) ? 0 : countClippedFaces(v1, v3, v4, clip_2);
- edge_rotation = false;
- }
- else {
- numTris_1 = countClippedFaces(v1, v2, v4, clip_1);
- numTris_2 = countClippedFaces(v2, v3, v4, clip_2);
- edge_rotation = true;
- if (G.debug & G_DEBUG_FREESTYLE) {
- printf("BlenderFileLoader::insertShapeNode: edge rotation is performed.\n");
- }
- }
- if (numTris_1 == 0 && numTris_2 == 0)
+ unsigned int numTris = countClippedFaces(v1, v2, v3, clip);
+ if (numTris == 0)
continue;
- bool fm, em1, em2, em3, em4;
- fm = (vlr->freestyle_face_mark) != 0;
- em1 = (vlr->freestyle_edge_mark & R_EDGE_V1V2) != 0;
- em2 = (vlr->freestyle_edge_mark & R_EDGE_V2V3) != 0;
- if (!vlr->v4) {
- em3 = (vlr->freestyle_edge_mark & R_EDGE_V3V1) != 0;
- em4 = false;
- }
- else {
- em3 = (vlr->freestyle_edge_mark & R_EDGE_V3V4) != 0;
- em4 = (vlr->freestyle_edge_mark & R_EDGE_V4V1) != 0;
+
+ bool fm = (ffa) ? (ffa[lt->poly].flag & FREESTYLE_FACE_MARK) != 0 : false;
+ bool em1 = false, em2 = false, em3 = false;
+
+ if (fed) {
+ em1 = testEdgeMark(me, fed, lt, 0);
+ em2 = testEdgeMark(me, fed, lt, 1);
+ em3 = testEdgeMark(me, fed, lt, 2);
}
- Material *mat = vlr->mat;
if (mat) {
tmpMat.setLine(mat->line_col[0], mat->line_col[1], mat->line_col[2], mat->line_col[3]);
tmpMat.setDiffuse(mat->r, mat->g, mat->b, mat->alpha);
@@ -629,43 +614,19 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
float triCoords[5][3], triNormals[5][3];
bool edgeMarks[5]; // edgeMarks[i] is for the edge between i-th and (i+1)-th vertices
- if (numTris_1 > 0) {
- if (!edge_rotation) {
- clipTriangle(numTris_1, triCoords, v1, v2, v3, triNormals, n1, n2, n3,
- edgeMarks, em1, em2, (!vlr->v4) ? em3 : false, clip_1);
- }
- else {
- clipTriangle(numTris_1, triCoords, v1, v2, v4, triNormals, n1, n2, n4,
- edgeMarks, em1, false, em4, clip_1);
- }
- for (i = 0; i < numTris_1; i++) {
- addTriangle(&ls, triCoords[0], triCoords[i + 1], triCoords[i + 2],
- triNormals[0], triNormals[i + 1], triNormals[i + 2],
- fm, (i == 0) ? edgeMarks[0] : false, edgeMarks[i + 1],
- (i == numTris_1 - 1) ? edgeMarks[i + 2] : false);
- _numFacesRead++;
- }
- }
-
- if (numTris_2 > 0) {
- if (!edge_rotation) {
- clipTriangle(numTris_2, triCoords, v1, v3, v4, triNormals, n1, n3, n4,
- edgeMarks, false, em3, em4, clip_2);
- }
- else {
- clipTriangle(numTris_2, triCoords, v2, v3, v4, triNormals, n2, n3, n4,
- edgeMarks, em2, em3, false, clip_2);
- }
- for (i = 0; i < numTris_2; i++) {
- addTriangle(&ls, triCoords[0], triCoords[i + 1], triCoords[i + 2],
- triNormals[0], triNormals[i + 1], triNormals[i + 2],
- fm, (i == 0) ? edgeMarks[0] : false, edgeMarks[i + 1],
- (i == numTris_2 - 1) ? edgeMarks[i + 2] : false);
- _numFacesRead++;
- }
+ clipTriangle(numTris, triCoords, v1, v2, v3, triNormals, n1, n2, n3,
+ edgeMarks, em1, em2, em3, clip);
+ for (i = 0; i < numTris; i++) {
+ addTriangle(&ls, triCoords[0], triCoords[i + 1], triCoords[i + 2],
+ triNormals[0], triNormals[i + 1], triNormals[i + 2],
+ fm, (i == 0) ? edgeMarks[0] : false, edgeMarks[i + 1],
+ (i == numTris - 1) ? edgeMarks[i + 2] : false);
+ _numFacesRead++;
}
}
+ MEM_freeN(mlooptri);
+
// We might have several times the same vertex. We want a clean
// shape with no real-vertex. Here, we are making a cleaning pass.
float *cleanVertices = NULL;
@@ -804,8 +765,8 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
cleanNIndices, niSize, MIndices, viSize, 0, 0, 0);
// sets the id of the rep
rep->setId(Id(id, 0));
- rep->setName(obi->ob->id.name + 2);
- rep->setLibraryPath(obi->ob->id.lib ? obi->ob->id.lib->name : NULL);
+ rep->setName(ob->id.name + 2);
+ rep->setLibraryPath(ob->id.lib ? ob->id.lib->name : NULL);
const BBox<Vec3r> bbox = BBox<Vec3r>(Vec3r(ls.minBBox[0], ls.minBBox[1], ls.minBBox[2]),
Vec3r(ls.maxBBox[0], ls.maxBBox[1], ls.maxBBox[2]));
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h
index ad92416801d..f9a8c787c08 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h
@@ -40,19 +40,30 @@
#include "../system/RenderMonitor.h"
extern "C" {
+#include "MEM_guardedalloc.h"
+
#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "renderdatabase.h"
#include "render_types.h"
+#include "BKE_customdata.h"
+#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_scene.h"
+#include "BLI_iterator.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
}
+#include "DEG_depsgraph_query.h"
+
#ifdef WITH_CXX_GUARDEDALLOC
#include "MEM_guardedalloc.h"
#endif
@@ -96,9 +107,8 @@ public:
inline void setRenderMonitor(RenderMonitor *iRenderMonitor) {_pRenderMonitor = iRenderMonitor;}
protected:
- void insertShapeNode(ObjectInstanceRen *obi, int id);
+ void insertShapeNode(Object *ob, Mesh *mesh, int id);
int testDegenerateTriangle(float v1[3], float v2[3], float v3[3]);
- bool testEdgeRotation(float v1[3], float v2[3], float v3[3], float v4[3]);
int countClippedFaces(float v1[3], float v2[3], float v3[3], int clip[3]);
void clipLine(float v1[3], float v2[3], float c[3], float z);
void clipTriangle(int numTris, float triCoords[][3], float v1[3], float v2[3], float v3[3],
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index 79f17756ca6..8aac83a6179 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -45,6 +45,7 @@ extern "C" {
#include "BKE_collection.h"
#include "BKE_customdata.h"
+#include "BKE_idprop.h"
#include "BKE_global.h"
#include "BKE_library.h" /* free_libblock */
#include "BKE_material.h"
@@ -76,7 +77,6 @@ const char *BlenderStrokeRenderer::uvNames[] = {"along_stroke", "along_stroke_ti
BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : StrokeRenderer()
{
freestyle_bmain = re->freestyle_bmain;
- freestyle_depsgraph = DEG_graph_new();
// for stroke mesh generation
_width = re->winx;
@@ -117,15 +117,30 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str
freestyle_scene->r.gauss = old_scene->r.gauss;
freestyle_scene->r.dither_intensity = old_scene->r.dither_intensity;
BKE_viewrender_copy(&freestyle_scene->view_render, &old_scene->view_render);
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Stroke rendering engine : " << freestyle_scene->view_render.engine_id << endl;
+ }
freestyle_scene->r.im_format.planes = R_IMF_PLANES_RGBA;
freestyle_scene->r.im_format.imtype = R_IMF_IMTYPE_PNG;
+ // Copy ID properties, including Cycles render properties
+ if (old_scene->id.properties) {
+ freestyle_scene->id.properties = IDP_CopyProperty_ex(old_scene->id.properties, 0);
+ }
+
+ if (STREQ(freestyle_scene->view_render.engine_id, RE_engine_id_CYCLES)) {
+ /* Render with transparent background. */
+ PointerRNA freestyle_scene_ptr;
+ RNA_id_pointer_create(&freestyle_scene->id, &freestyle_scene_ptr);
+ PointerRNA freestyle_cycles_ptr = RNA_pointer_get(&freestyle_scene_ptr, "cycles");
+ RNA_boolean_set(&freestyle_cycles_ptr, "film_transparent", 1);
+ }
+
if (G.debug & G_DEBUG_FREESTYLE) {
printf("%s: %d thread(s)\n", __func__, BKE_render_num_threads(&freestyle_scene->r));
}
BKE_scene_set_background(freestyle_bmain, freestyle_scene);
- DEG_graph_id_tag_update(freestyle_bmain, freestyle_depsgraph, &freestyle_scene->id, 0);
// Scene layer.
ViewLayer *view_layer = (ViewLayer *)freestyle_scene->view_layers.first;
@@ -133,7 +148,6 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str
// Camera
Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, view_layer, OB_CAMERA, NULL);
- DEG_graph_id_tag_update(freestyle_bmain, freestyle_depsgraph, &object_camera->id, 0);
Camera *camera = (Camera *)object_camera->data;
camera->type = CAM_ORTHO;
@@ -162,7 +176,10 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str
else
_nodetree_hash = NULL;
- // New IDs were added, tag relations for update.
+ // Depsgraph
+ freestyle_depsgraph = DEG_graph_new(re->scene, view_layer, DAG_EVAL_RENDER);
+ DEG_graph_id_tag_update(freestyle_bmain, freestyle_depsgraph, &freestyle_scene->id, 0);
+ DEG_graph_id_tag_update(freestyle_bmain, freestyle_depsgraph, &object_camera->id, 0);
DEG_graph_tag_relations_update(freestyle_depsgraph);
}
@@ -200,11 +217,11 @@ BlenderStrokeRenderer::~BlenderStrokeRenderer()
}
// Make sure we don't have any bases which might reference freed objects.
- FOREACH_SCENE_COLLECTION(freestyle_scene, sc)
+ FOREACH_SCENE_COLLECTION_BEGIN(freestyle_scene, sc)
{
BLI_freelistN(&sc->objects);
}
- FOREACH_SCENE_COLLECTION_END
+ FOREACH_SCENE_COLLECTION_END;
BLI_freelistN(&view_layer->object_bases);
// release materials
@@ -478,28 +495,6 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
ma = BlenderStrokeRenderer::GetStrokeShader(freestyle_bmain, nt, false);
BLI_ghash_insert(_nodetree_hash, nt, ma);
}
-
- if (STREQ(freestyle_scene->view_render.engine_id, RE_engine_id_CYCLES)) {
- PointerRNA scene_ptr, freestyle_scene_ptr;
- RNA_pointer_create(NULL, &RNA_Scene, old_scene, &scene_ptr);
- RNA_pointer_create(NULL, &RNA_Scene, freestyle_scene, &freestyle_scene_ptr);
-
- PointerRNA cycles_ptr = RNA_pointer_get(&scene_ptr, "cycles");
- PointerRNA freestyle_cycles_ptr = RNA_pointer_get(&freestyle_scene_ptr, "cycles");
-
- int flag;
- RNA_STRUCT_BEGIN(&freestyle_cycles_ptr, prop)
- {
- flag = RNA_property_flag(prop);
- if (flag & PROP_HIDDEN)
- continue;
- RNA_property_copy(&freestyle_cycles_ptr, &cycles_ptr, prop, -1);
- }
- RNA_STRUCT_END;
-
- RNA_boolean_set(&freestyle_cycles_ptr, "film_transparent", 1);
- }
-
iStrokeRep->setMaterial(ma);
}
else {
@@ -971,7 +966,6 @@ Render *BlenderStrokeRenderer::RenderScene(Render * /*re*/, bool render)
Render *freestyle_render = RE_NewSceneRender(freestyle_scene);
ViewLayer *view_layer = (ViewLayer *)freestyle_scene->view_layers.first;
DEG_graph_relations_update(freestyle_depsgraph, freestyle_bmain, freestyle_scene, view_layer);
- freestyle_render->depsgraph = freestyle_depsgraph;
RE_RenderFreestyleStrokes(freestyle_render, freestyle_bmain, freestyle_scene,
render && get_stroke_count() > 0);
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 0ac842d90a0..bf0e6ea3368 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -55,7 +55,6 @@ set(SRC
intern/gpu_batch_presets.c
intern/gpu_buffers.c
intern/gpu_codegen.c
- intern/gpu_compositing.c
intern/gpu_debug.c
intern/gpu_draw.c
intern/gpu_extensions.c
@@ -81,7 +80,6 @@ set(SRC
shaders/gpu_shader_fx_dof_hq_frag.glsl
shaders/gpu_shader_fx_dof_hq_vert.glsl
shaders/gpu_shader_fx_dof_hq_geo.glsl
- shaders/gpu_shader_fullscreen_vert.glsl
shaders/gpu_shader_material.glsl
shaders/gpu_shader_sep_gaussian_blur_frag.glsl
shaders/gpu_shader_sep_gaussian_blur_vert.glsl
@@ -99,7 +97,6 @@ set(SRC
GPU_basic_shader.h
GPU_batch.h
GPU_buffers.h
- GPU_compositing.h
GPU_debug.h
GPU_draw.h
GPU_extensions.h
@@ -135,6 +132,12 @@ data_to_c_simple(shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl
data_to_c_simple(shaders/gpu_shader_flat_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_widget_base_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_widget_base_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_widget_shadow_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_widget_shadow_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_nodelink_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_nodelink_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_flat_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_line_dashed_frag.glsl SRC)
@@ -142,14 +145,18 @@ data_to_c_simple(shaders/gpu_shader_2D_line_dashed_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_smooth_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_smooth_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_image_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_image_rect_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_image_multi_rect_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_linear_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_shuffle_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_mask_uniform_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_modulate_alpha_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_alpha_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_color_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_varying_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_depth_linear_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_depth_copy_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_interlace_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_image_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_vert.glsl SRC)
@@ -174,7 +181,7 @@ data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_instance_bone_envelope_solid_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_instance_bone_envelope_wire_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_instance_mball_helpers_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_mball_handles_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_groundline_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_groundpoint_vert.glsl SRC)
@@ -202,7 +209,10 @@ data_to_c_simple(shaders/gpu_shader_edges_overlay_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_edges_overlay_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_edges_overlay_simple_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_edges_overlay_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_text_simple_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_text_simple_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_text_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_text_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_text_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_keyframe_diamond_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_keyframe_diamond_frag.glsl SRC)
@@ -221,15 +231,6 @@ data_to_c_simple(shaders/gpu_shader_vertex.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vertex_world.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fullscreen_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_ssao_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_dof_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_dof_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_dof_hq_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_dof_hq_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_dof_hq_geo.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_depth_resolve.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_lib.glsl SRC)
if(WITH_GAMEENGINE)
add_definitions(-DWITH_GAMEENGINE)
diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h
index d2f3409dc07..760faeff7b1 100644
--- a/source/blender/gpu/GPU_batch.h
+++ b/source/blender/gpu/GPU_batch.h
@@ -32,6 +32,7 @@
#define __GPU_BATCH_H__
#include "../../../intern/gawain/gawain/gwn_batch.h"
+#include "../../../intern/gawain/gawain/gwn_batch_private.h"
struct rctf;
@@ -39,6 +40,7 @@ struct rctf;
// #include "gawain/batch.h"
#include "BLI_compiler_attrs.h"
+#include "BLI_sys_types.h"
#include "GPU_shader.h"
@@ -58,11 +60,15 @@ void gpu_batch_init(void);
void gpu_batch_exit(void);
/* gpu_batch_presets.c */
+/* Only use by draw manager. Use the presets function instead for interface. */
+Gwn_Batch *gpu_batch_sphere(int lat_res, int lon_res) ATTR_WARN_UNUSED_RESULT;
/* Replacement for gluSphere */
Gwn_Batch *GPU_batch_preset_sphere(int lod) ATTR_WARN_UNUSED_RESULT;
Gwn_Batch *GPU_batch_preset_sphere_wire(int lod) ATTR_WARN_UNUSED_RESULT;
void gpu_batch_presets_init(void);
+void gpu_batch_presets_register(Gwn_Batch *preset_batch);
+void gpu_batch_presets_reset(void);
void gpu_batch_presets_exit(void);
#endif /* __GPU_BATCH_H__ */
diff --git a/source/blender/gpu/GPU_compositing.h b/source/blender/gpu/GPU_compositing.h
deleted file mode 100644
index d506d91a9aa..00000000000
--- a/source/blender/gpu/GPU_compositing.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2005 Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Antony Riakiotakis.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file GPU_compositing.h
- * \ingroup gpu
- */
-
-#ifndef __GPU_COMPOSITING_H__
-#define __GPU_COMPOSITING_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* opaque handle for framebuffer compositing effects (defined in gpu_compositing.c )*/
-typedef struct GPUFX GPUFX;
-struct GPUDOFSettings;
-struct GPUSSAOSettings;
-struct GPUOffScreen;
-struct GPUFXSettings;
-struct rcti;
-struct Scene;
-struct GPUShader;
-enum eGPUFXFlags;
-
-/**** Public API *****/
-
-typedef enum GPUFXShaderEffect {
- /* Screen space ambient occlusion shader */
- GPU_SHADER_FX_SSAO = 1,
-
- /* depth of field passes. Yep, quite a complex effect */
- GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE = 2,
- GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO = 3,
- GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE = 4,
- GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR = 5,
- GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE = 6,
-
- /* high quality */
- GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE = 7,
- GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO = 8,
- GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE = 9,
-
- GPU_SHADER_FX_DEPTH_RESOLVE = 10,
-} GPUFXShaderEffect;
-
-/* keep in synch with enum above! */
-#define MAX_FX_SHADERS 11
-
-/* generate a new FX compositor */
-GPUFX *GPU_fx_compositor_create(void);
-
-/* destroy a text compositor */
-void GPU_fx_compositor_destroy(GPUFX *fx);
-
-/* initialize a framebuffer with size taken from the viewport */
-bool GPU_fx_compositor_initialize_passes(
- GPUFX *fx, const struct rcti *rect, const struct rcti *scissor_rect,
- const struct GPUFXSettings *fx_settings);
-
-/* do compositing on the fx passes that have been initialized */
-bool GPU_fx_do_composite_pass(
- GPUFX *fx, float projmat[4][4], bool is_persp,
- struct Scene *scene, struct GPUOffScreen *ofs);
-
-/* bind new depth buffer for XRay pass */
-void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray);
-
-/* resolve a final depth buffer by compositing the XRay and normal depth buffers */
-void GPU_fx_compositor_XRay_resolve(GPUFX *fx);
-
-void GPU_fx_compositor_init_dof_settings(struct GPUDOFSettings *dof);
-void GPU_fx_compositor_init_ssao_settings(struct GPUSSAOSettings *ssao);
-
-
-/* initialize and cache the shader unform interface for effects */
-void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect effect);
-#ifdef __cplusplus
-}
-#endif
-
-#endif // __GPU_COMPOSITING_H__
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 8d29632fc71..9bbf46b2a1f 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -47,6 +47,8 @@ struct RegionView3D;
struct SmokeModifierData;
struct DupliObject;
+#include "DNA_object_enums.h"
+
/* OpenGL drawing functions related to shading. These are also
* shared with the game engine, where there were previously
* duplicates of some of these functions. */
@@ -73,9 +75,10 @@ void GPU_disable_program_point_size(void);
* GPU_object_material_bind returns 0 if drawing should be skipped
* - after drawing, the material must be disabled again */
-void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d,
- struct Scene *scene, struct ViewLayer *view_layer,
- struct Object *ob, bool glsl, bool *do_alpha_after);
+void GPU_begin_object_materials(
+ struct View3D *v3d, struct RegionView3D *rv3d,
+ struct Scene *scene, struct ViewLayer *view_layer,
+ struct Object *ob, bool glsl, bool *do_alpha_after);
void GPU_end_object_materials(void);
bool GPU_object_materials_check(void);
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index d860431b04f..d36b0ea15be 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -64,7 +64,6 @@ typedef enum GPUDeviceType {
GPU_DEVICE_INTEL = (1 << 2),
GPU_DEVICE_SOFTWARE = (1 << 3),
GPU_DEVICE_UNKNOWN = (1 << 4),
- GPU_DEVICE_AMD_VEGA = (1 << 5),
GPU_DEVICE_ANY = (0xff)
} GPUDeviceType;
diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h
index c58d98c201e..0ab15a4ea47 100644
--- a/source/blender/gpu/GPU_framebuffer.h
+++ b/source/blender/gpu/GPU_framebuffer.h
@@ -36,61 +36,158 @@
extern "C" {
#endif
+struct GPUTexture;
+
+typedef struct GPUAttachment {
+ struct GPUTexture *tex;
+ int mip, layer;
+} GPUAttachment;
+
+typedef enum GPUFrameBufferBits{
+ GPU_COLOR_BIT = (1 << 0),
+ GPU_DEPTH_BIT = (1 << 1),
+ GPU_STENCIL_BIT = (1 << 2),
+} GPUFrameBufferBits;
+
typedef struct GPUFrameBuffer GPUFrameBuffer;
typedef struct GPUOffScreen GPUOffScreen;
-struct GPUTexture;
/* GPU Framebuffer
* - this is a wrapper for an OpenGL framebuffer object (FBO). in practice
* multiple FBO's may be created, to get around limitations on the number
* of attached textures and the dimension requirements.
- * - after any of the GPU_framebuffer_* functions, GPU_framebuffer_restore must
- * be called before rendering to the window framebuffer again */
-
-void GPU_texture_bind_as_framebuffer(struct GPUTexture *tex);
+ * - actual FBO creation & config is deferred until GPU_framebuffer_bind or
+ * GPU_framebuffer_check_valid to allow creation & config while another
+ * opengl context is bound (since FBOs are not shared between ogl contexts).
+ */
GPUFrameBuffer *GPU_framebuffer_create(void);
-bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int mip);
-bool GPU_framebuffer_texture_layer_attach(
- GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int layer, int mip);
-bool GPU_framebuffer_texture_cubeface_attach(
- GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int face, int mip);
-void GPU_framebuffer_texture_detach(struct GPUTexture *tex);
-void GPU_framebuffer_bind(GPUFrameBuffer *fb);
-void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
-void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, struct GPUTexture *tex);
void GPU_framebuffer_free(GPUFrameBuffer *fb);
+void GPU_framebuffer_bind(GPUFrameBuffer *fb);
+void GPU_framebuffer_restore(void);
+
+bool GPU_framebuffer_bound(GPUFrameBuffer *fb);
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]);
-void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot);
+/* internal use only */
+unsigned int GPU_framebuffer_current_get(void);
-bool GPU_framebuffer_bound(GPUFrameBuffer *fb);
+#define GPU_FRAMEBUFFER_FREE_SAFE(fb) do { \
+ if (fb != NULL) { \
+ GPU_framebuffer_free(fb); \
+ fb = NULL; \
+ } \
+} while (0)
-void GPU_framebuffer_restore(void);
-void GPU_framebuffer_blur(
- GPUFrameBuffer *fb, struct GPUTexture *tex,
- GPUFrameBuffer *blurfb, struct GPUTexture *blurtex);
+/* Framebuffer setup : You need to call GPU_framebuffer_bind for theses
+ * to be effective. */
+
+void GPU_framebuffer_texture_attach(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int mip);
+void GPU_framebuffer_texture_layer_attach(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int layer, int mip);
+void GPU_framebuffer_texture_cubeface_attach(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int face, int mip);
+void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, struct GPUTexture *tex);
+void GPU_framebuffer_texture_detach_slot(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int type);
+
+/**
+ * How to use GPU_framebuffer_ensure_config().
+ *
+ * Example :
+ * GPU_framebuffer_ensure_config(&fb, {
+ * GPU_ATTACHMENT_TEXTURE(depth), // must be depth buffer
+ * GPU_ATTACHMENT_TEXTURE(tex1),
+ * GPU_ATTACHMENT_TEXTURE_CUBEFACE(tex2, 0),
+ * GPU_ATTACHMENT_TEXTURE_LAYER_MIP(tex2, 0, 0)
+ * })
+ *
+ * Note : Unspecified attachements (i.e: those beyond the last
+ * GPU_ATTACHMENT_* in GPU_framebuffer_ensure_config list)
+ * are left unchanged.
+ * Note : Make sure that the dimensions of your textures matches
+ * otherwise you will have an invalid framebuffer error.
+ **/
+#define GPU_framebuffer_ensure_config(_fb, ...) do { \
+ if (*(_fb) == NULL) { \
+ *(_fb) = GPU_framebuffer_create(); \
+ } \
+ GPUAttachment config[] = __VA_ARGS__; \
+ GPU_framebuffer_config_array(*(_fb), config, (sizeof(config) / sizeof(GPUAttachment))); \
+} while (0)
+
+void GPU_framebuffer_config_array(GPUFrameBuffer *fb, const GPUAttachment *config, int config_ct);
+
+#define GPU_ATTACHMENT_NONE \
+ {.tex = NULL, .layer = -1, .mip = 0}
+#define GPU_ATTACHMENT_LEAVE \
+ {.tex = NULL, .layer = -1, .mip = -1}
+#define GPU_ATTACHMENT_TEXTURE(_tex) \
+ {.tex = _tex, .layer = -1, .mip = 0}
+#define GPU_ATTACHMENT_TEXTURE_MIP(_tex, _mip) \
+ {.tex = _tex, .layer = -1, .mip = _mip}
+#define GPU_ATTACHMENT_TEXTURE_LAYER(_tex, _layer) \
+ {.tex = _tex, .layer = _layer, .mip = 0}
+#define GPU_ATTACHMENT_TEXTURE_LAYER_MIP(_tex, _layer, _mip) \
+ {.tex = _tex, .layer = _layer, .mip = _mip}
+#define GPU_ATTACHMENT_TEXTURE_CUBEFACE(_tex, _face) \
+ {.tex = _tex, .layer = _face, .mip = 0}
+#define GPU_ATTACHMENT_TEXTURE_CUBEFACE_MIP(_tex, _face, _mip) \
+ {.tex = _tex, .layer = _face, .mip = _mip}
+
+/* Framebuffer operations */
+
+void GPU_framebuffer_viewport_set(GPUFrameBuffer *fb, int x, int y, int w, int h);
+
+void GPU_framebuffer_clear(
+ GPUFrameBuffer *fb, GPUFrameBufferBits buffers,
+ const float clear_col[4], float clear_depth, unsigned int clear_stencil);
+
+#define GPU_framebuffer_clear_color(fb, col) \
+ GPU_framebuffer_clear(fb, GPU_COLOR_BIT, col, 0.0f, 0x00)
+
+#define GPU_framebuffer_clear_depth(fb, depth) \
+ GPU_framebuffer_clear(fb, GPU_DEPTH_BIT, NULL, depth, 0x00)
+
+#define GPU_framebuffer_clear_color_depth(fb, col, depth) \
+ GPU_framebuffer_clear(fb, GPU_COLOR_BIT | GPU_DEPTH_BIT, col, depth, 0x00)
+
+#define GPU_framebuffer_clear_stencil(fb, stencil) \
+ GPU_framebuffer_clear(fb, GPU_STENCIL_BIT, NULL, 0.0f, stencil)
+
+#define GPU_framebuffer_clear_depth_stencil(fb, depth, stencil) \
+ GPU_framebuffer_clear(fb, GPU_DEPTH_BIT | GPU_STENCIL_BIT, NULL, depth, stencil)
+
+#define GPU_framebuffer_clear_color_depth_stencil(fb, col, depth, stencil) \
+ GPU_framebuffer_clear(fb, GPU_COLOR_BIT | GPU_DEPTH_BIT | GPU_STENCIL_BIT, col, depth, stencil)
+
+void GPU_framebuffer_read_depth(GPUFrameBuffer *fb, int x, int y, int w, int h, float *data);
+void GPU_framebuffer_read_color(
+ GPUFrameBuffer *fb, int x, int y, int w, int h, int channels, int slot, float *data);
void GPU_framebuffer_blit(
GPUFrameBuffer *fb_read, int read_slot,
- GPUFrameBuffer *fb_write, int write_slot, bool use_depth, bool use_stencil);
+ GPUFrameBuffer *fb_write, int write_slot,
+ GPUFrameBufferBits blit_buffers);
void GPU_framebuffer_recursive_downsample(
- GPUFrameBuffer *fb, struct GPUTexture *tex, int num_iter,
+ GPUFrameBuffer *fb, int max_lvl,
void (*callback)(void *userData, int level), void *userData);
/* GPU OffScreen
* - wrapper around framebuffer and texture for simple offscreen drawing
- * - changes size if graphics card can't support it */
+ */
-GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, bool high_bitdepth, char err_out[256]);
+GPUOffScreen *GPU_offscreen_create(int width, int height, int samples,
+ bool depth, bool high_bitdepth, char err_out[256]);
void GPU_offscreen_free(GPUOffScreen *ofs);
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore);
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
int GPU_offscreen_width(const GPUOffScreen *ofs);
int GPU_offscreen_height(const GPUOffScreen *ofs);
-int GPU_offscreen_color_texture(const GPUOffScreen *ofs);
+struct GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *ofs);
void GPU_offscreen_viewport_data_get(
GPUOffScreen *ofs,
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 698f3ada2a3..1d2b234e7f3 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -110,7 +110,8 @@ typedef enum GPUBuiltin {
GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14),
GPU_OBJECT_INFO = (1 << 15),
GPU_VOLUME_DENSITY = (1 << 16),
- GPU_VOLUME_FLAME = (1 << 17)
+ GPU_VOLUME_FLAME = (1 << 17),
+ GPU_VOLUME_TEMPERATURE = (1 << 18)
} GPUBuiltin;
typedef enum GPUOpenGLBuiltin {
@@ -135,14 +136,19 @@ typedef enum GPUBlendMode {
typedef struct GPUNodeStack {
GPUType type;
- const char *name;
float vec[4];
struct GPUNodeLink *link;
bool hasinput;
bool hasoutput;
short sockettype;
+ bool end;
} GPUNodeStack;
+typedef enum GPUMaterialStatus {
+ GPU_MAT_FAILED = 0,
+ GPU_MAT_QUEUED,
+ GPU_MAT_SUCCESS,
+} GPUMaterialStatus;
#define GPU_DYNAMIC_GROUP_FROM_TYPE(f) ((f) & 0xFFFF0000)
@@ -244,9 +250,11 @@ GPUMaterial *GPU_material_from_nodetree_find(
struct ListBase *gpumaterials, const void *engine_type, int options);
GPUMaterial *GPU_material_from_nodetree(
struct Scene *scene, struct bNodeTree *ntree, struct ListBase *gpumaterials, const void *engine_type, int options,
- const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines);
+ const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines, bool deferred);
GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma, bool use_opensubdiv);
GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma, bool use_opensubdiv);
+void GPU_material_generate_pass(
+ GPUMaterial *mat, const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines);
void GPU_material_free(struct ListBase *gpumaterial);
void GPU_materials_free(void);
@@ -262,6 +270,8 @@ bool GPU_material_bound(GPUMaterial *material);
struct Scene *GPU_material_scene(GPUMaterial *material);
GPUMatType GPU_Material_get_type(GPUMaterial *material);
struct GPUPass *GPU_material_get_pass(GPUMaterial *material);
+struct ListBase *GPU_material_get_inputs(GPUMaterial *material);
+GPUMaterialStatus GPU_material_status(GPUMaterial *mat);
struct GPUUniformBuffer *GPU_material_get_uniform_buffer(GPUMaterial *material);
void GPU_material_create_uniform_buffer(GPUMaterial *material, struct ListBase *inputs);
@@ -357,10 +367,9 @@ void GPU_zenith_update_color(float color[3]);
struct GPUParticleInfo
{
float scalprops[4];
- float location[3];
+ float location[4];
float velocity[3];
float angular_velocity[3];
- int random_id;
};
#ifdef WITH_OPENSUBDIV
@@ -369,6 +378,9 @@ void GPU_material_update_fvar_offset(GPUMaterial *gpu_material,
struct DerivedMesh *dm);
#endif
+void GPU_pass_cache_garbage_collect(void);
+void GPU_pass_cache_free(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/GPU_select.h b/source/blender/gpu/GPU_select.h
index 0617d58f3b6..f1342a1f6b8 100644
--- a/source/blender/gpu/GPU_select.h
+++ b/source/blender/gpu/GPU_select.h
@@ -47,6 +47,7 @@ enum {
void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const struct rcti *input, char mode, int oldhits);
bool GPU_select_load_id(unsigned int id);
+void GPU_select_finalize(void);
unsigned int GPU_select_end(void);
bool GPU_select_query_check_active(void);
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index f2119a117e5..b33df9fdb20 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -72,9 +72,6 @@ int GPU_shader_get_program(GPUShader *shader);
void *GPU_shader_get_interface(GPUShader *shader);
-void *GPU_fx_shader_get_interface(GPUShader *shader);
-void GPU_fx_shader_set_interface(GPUShader *shader, void *interface);
-
int GPU_shader_get_uniform(GPUShader *shader, const char *name);
int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin);
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name);
@@ -100,6 +97,7 @@ typedef enum GPUBuiltinShader {
/* specialized drawing */
GPU_SHADER_TEXT,
+ GPU_SHADER_TEXT_SIMPLE,
GPU_SHADER_EDGES_FRONT_BACK_PERSP,
GPU_SHADER_EDGES_FRONT_BACK_ORTHO,
GPU_SHADER_EDGES_OVERLAY_SIMPLE,
@@ -113,8 +111,12 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_2D_UNIFORM_COLOR,
GPU_SHADER_2D_FLAT_COLOR,
GPU_SHADER_2D_SMOOTH_COLOR,
+ GPU_SHADER_2D_IMAGE,
GPU_SHADER_2D_IMAGE_COLOR,
GPU_SHADER_2D_IMAGE_ALPHA_COLOR,
+ GPU_SHADER_2D_IMAGE_ALPHA,
+ GPU_SHADER_2D_IMAGE_RECT_COLOR,
+ GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR,
GPU_SHADER_2D_CHECKER,
GPU_SHADER_2D_DIAG_STRIPES,
/* for simple 3D drawing */
@@ -131,8 +133,8 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR,
GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR,
GPU_SHADER_3D_IMAGE_MODULATE_ALPHA,
- GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA,
GPU_SHADER_3D_IMAGE_DEPTH,
+ GPU_SHADER_3D_IMAGE_DEPTH_COPY,
/* stereo 3d */
GPU_SHADER_2D_IMAGE_INTERLACE,
/* points */
@@ -169,11 +171,17 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, /* Uniformly scaled */
GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE,
GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR,
+ /* specialized for UI drawing */
+ GPU_SHADER_2D_WIDGET_BASE,
+ GPU_SHADER_2D_WIDGET_BASE_INST,
+ GPU_SHADER_2D_WIDGET_SHADOW,
+ GPU_SHADER_2D_NODELINK,
+ GPU_SHADER_2D_NODELINK_INST,
GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID,
GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_WIRE,
- GPU_SHADER_3D_INSTANCE_MBALL_HELPERS,
+ GPU_SHADER_3D_INSTANCE_MBALL_HANDLES,
GPU_NUM_BUILTIN_SHADERS /* (not an actual shader) */
} GPUBuiltinShader;
@@ -189,7 +197,6 @@ typedef enum GPUInterlaceShader {
} GPUInterlaceShader;
GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader);
-GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp);
void GPU_shader_free_builtin_shaders(void);
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index e74d9a3291d..7c33153ee01 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -70,6 +70,7 @@ typedef enum GPUTextureFormat {
GPU_RG16I,
GPU_R32F,
GPU_R16F,
+ GPU_R16I,
GPU_RG8,
GPU_R8,
#if 0
@@ -88,7 +89,6 @@ typedef enum GPUTextureFormat {
GPU_RG8UI,
GPU_R32I,
GPU_R32UI,
- GPU_R16I,
GPU_R16UI,
GPU_R16,
GPU_R8I,
@@ -189,16 +189,18 @@ void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter);
void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter);
void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat);
-struct GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex);
-int GPU_texture_framebuffer_attachment(GPUTexture *tex);
-void GPU_texture_framebuffer_set(GPUTexture *tex, struct GPUFrameBuffer *fb, int attachment);
+void GPU_texture_attach_framebuffer(GPUTexture *tex, struct GPUFrameBuffer *fb, int attachment);
+int GPU_texture_detach_framebuffer(GPUTexture *tex, struct GPUFrameBuffer *fb);
int GPU_texture_target(const GPUTexture *tex);
int GPU_texture_width(const GPUTexture *tex);
int GPU_texture_height(const GPUTexture *tex);
-int GPU_texture_format(const GPUTexture *tex);
+GPUTextureFormat GPU_texture_format(const GPUTexture *tex);
+int GPU_texture_samples(const GPUTexture *tex);
+bool GPU_texture_cube(const GPUTexture *tex);
bool GPU_texture_depth(const GPUTexture *tex);
bool GPU_texture_stencil(const GPUTexture *tex);
+bool GPU_texture_integer(const GPUTexture *tex);
int GPU_texture_opengl_bindcode(const GPUTexture *tex);
#ifdef __cplusplus
diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h
index 580ff64befb..ca7d5ae7ceb 100644
--- a/source/blender/gpu/GPU_viewport.h
+++ b/source/blender/gpu/GPU_viewport.h
@@ -46,7 +46,7 @@ typedef struct GPUViewport GPUViewport;
/* Contains memory pools informations */
typedef struct ViewportMemoryPool {
struct BLI_mempool *calls;
- struct BLI_mempool *calls_generate;
+ struct BLI_mempool *states;
struct BLI_mempool *shgroups;
struct BLI_mempool *uniforms;
struct BLI_mempool *passes;
@@ -83,7 +83,6 @@ typedef struct ViewportEngineData {
/* Profiling data */
double init_time;
- double cache_time;
double render_time;
double background_time;
} ViewportEngineData;
@@ -98,6 +97,7 @@ typedef struct ViewportEngineData_Info {
GPUViewport *GPU_viewport_create(void);
void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect);
void GPU_viewport_unbind(GPUViewport *viewport);
+void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect);
void GPU_viewport_free(GPUViewport *viewport);
GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs);
@@ -113,6 +113,9 @@ void *GPU_viewport_texture_list_get(GPUViewport *viewport);
void GPU_viewport_size_get(const GPUViewport *viewport, int size[2]);
void GPU_viewport_size_set(GPUViewport *viewport, const int size[2]);
+/* Profiling */
+double *GPU_viewport_cache_time_get(GPUViewport *viewport);
+
void GPU_viewport_tag_update(GPUViewport *viewport);
bool GPU_viewport_do_update(GPUViewport *viewport);
@@ -122,13 +125,4 @@ GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine,
bool GPU_viewport_engines_data_validate(GPUViewport *viewport, unsigned int hash);
void GPU_viewport_cache_release(GPUViewport *viewport);
-/* debug */
-bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256]);
-void GPU_viewport_debug_depth_free(GPUViewport *viewport);
-void GPU_viewport_debug_depth_store(GPUViewport *viewport, const int x, const int y);
-void GPU_viewport_debug_depth_draw(GPUViewport *viewport, const float znear, const float zfar);
-bool GPU_viewport_debug_depth_is_valid(GPUViewport *viewport);
-int GPU_viewport_debug_depth_width(const GPUViewport *viewport);
-int GPU_viewport_debug_depth_height(const GPUViewport *viewport);
-
#endif // __GPU_VIEWPORT_H__
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
index 0400fc1025b..332102aca46 100644
--- a/source/blender/gpu/intern/gpu_batch.c
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -34,7 +34,7 @@
#include "BLI_utildefines.h"
#include "BLI_rect.h"
#include "BLI_math.h"
-#include "BLI_polyfill2d.h"
+#include "BLI_polyfill_2d.h"
#include "BLI_sort_utils.h"
diff --git a/source/blender/gpu/intern/gpu_batch_presets.c b/source/blender/gpu/intern/gpu_batch_presets.c
index 9db04832a51..10cbd16490b 100644
--- a/source/blender/gpu/intern/gpu_batch_presets.c
+++ b/source/blender/gpu/intern/gpu_batch_presets.c
@@ -31,6 +31,11 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_threads.h"
+#include "BLI_listbase.h"
+#include "MEM_guardedalloc.h"
+
+#include "UI_interface.h"
#include "GPU_batch.h"
#include "gpu_shader_private.h"
@@ -50,14 +55,24 @@ static struct {
struct {
uint pos, nor;
} attr_id;
-} g_presets_3d = {0};
+} g_presets_3d = {{0}};
-/* We may want 2D presets later. */
+static ListBase presets_list = {NULL, NULL};
/* -------------------------------------------------------------------- */
/** \name 3D Primitives
* \{ */
+static Gwn_VertFormat *preset_3D_format(void)
+{
+ if (g_presets_3d.format.attrib_ct == 0) {
+ Gwn_VertFormat *format = &g_presets_3d.format;
+ g_presets_3d.attr_id.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ g_presets_3d.attr_id.nor = GWN_vertformat_attr_add(format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+ return &g_presets_3d.format;
+}
+
static void batch_sphere_lat_lon_vert(
Gwn_VertBufRaw *pos_step, Gwn_VertBufRaw *nor_step,
float lat, float lon)
@@ -71,13 +86,13 @@ static void batch_sphere_lat_lon_vert(
}
/* Replacement for gluSphere */
-static Gwn_Batch *batch_sphere(int lat_res, int lon_res)
+Gwn_Batch *gpu_batch_sphere(int lat_res, int lon_res)
{
const float lon_inc = 2 * M_PI / lon_res;
const float lat_inc = M_PI / lat_res;
float lon, lat;
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&g_presets_3d.format);
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(preset_3D_format());
const uint vbo_len = (lat_res - 1) * lon_res * 6;
GWN_vertbuf_data_alloc(vbo, vbo_len);
@@ -115,7 +130,7 @@ static Gwn_Batch *batch_sphere_wire(int lat_res, int lon_res)
const float lat_inc = M_PI / lat_res;
float lon, lat;
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&g_presets_3d.format);
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(preset_3D_format());
const uint vbo_len = (lat_res * lon_res * 2) + ((lat_res - 1) * lon_res * 2);
GWN_vertbuf_data_alloc(vbo, vbo_len);
@@ -146,6 +161,7 @@ static Gwn_Batch *batch_sphere_wire(int lat_res, int lon_res)
Gwn_Batch *GPU_batch_preset_sphere(int lod)
{
BLI_assert(lod >= 0 && lod <= 2);
+ BLI_assert(BLI_thread_is_main());
if (lod == 0) {
return g_presets_3d.batch.sphere_low;
@@ -161,6 +177,7 @@ Gwn_Batch *GPU_batch_preset_sphere(int lod)
Gwn_Batch *GPU_batch_preset_sphere_wire(int lod)
{
BLI_assert(lod >= 0 && lod <= 1);
+ BLI_assert(BLI_thread_is_main());
if (lod == 0) {
return g_presets_3d.batch.sphere_wire_low;
@@ -175,26 +192,45 @@ Gwn_Batch *GPU_batch_preset_sphere_wire(int lod)
void gpu_batch_presets_init(void)
{
- if (g_presets_3d.format.attrib_ct == 0) {
- Gwn_VertFormat *format = &g_presets_3d.format;
- g_presets_3d.attr_id.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- g_presets_3d.attr_id.nor = GWN_vertformat_attr_add(format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- }
-
/* Hard coded resolution */
- g_presets_3d.batch.sphere_low = batch_sphere(8, 16);
- g_presets_3d.batch.sphere_med = batch_sphere(16, 10);
- g_presets_3d.batch.sphere_high = batch_sphere(32, 24);
+ g_presets_3d.batch.sphere_low = gpu_batch_sphere(8, 16);
+ gpu_batch_presets_register(g_presets_3d.batch.sphere_low);
+
+ g_presets_3d.batch.sphere_med = gpu_batch_sphere(16, 10);
+ gpu_batch_presets_register(g_presets_3d.batch.sphere_med);
+
+ g_presets_3d.batch.sphere_high = gpu_batch_sphere(32, 24);
+ gpu_batch_presets_register(g_presets_3d.batch.sphere_high);
g_presets_3d.batch.sphere_wire_low = batch_sphere_wire(6, 8);
+ gpu_batch_presets_register(g_presets_3d.batch.sphere_wire_low);
+
g_presets_3d.batch.sphere_wire_med = batch_sphere_wire(8, 16);
+ gpu_batch_presets_register(g_presets_3d.batch.sphere_wire_med);
+}
+
+void gpu_batch_presets_register(Gwn_Batch *preset_batch)
+{
+ BLI_addtail(&presets_list, BLI_genericNodeN(preset_batch));
+}
+
+void gpu_batch_presets_reset(void)
+{
+ /* Reset vao caches for these every time we switch opengl context.
+ * This way they will draw correctly for each window. */
+ LinkData *link = presets_list.first;
+ for (link = presets_list.first; link; link = link->next) {
+ Gwn_Batch *preset = link->data;
+ gwn_batch_vao_cache_clear(preset);
+ }
}
void gpu_batch_presets_exit(void)
{
- GWN_batch_discard(g_presets_3d.batch.sphere_low);
- GWN_batch_discard(g_presets_3d.batch.sphere_med);
- GWN_batch_discard(g_presets_3d.batch.sphere_high);
- GWN_batch_discard(g_presets_3d.batch.sphere_wire_low);
- GWN_batch_discard(g_presets_3d.batch.sphere_wire_med);
+ LinkData *link;
+ while ((link = BLI_pophead(&presets_list))) {
+ Gwn_Batch *preset = link->data;
+ GWN_batch_discard(preset);
+ MEM_freeN(link);
+ }
}
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index d0efee79ab0..3367a568bc5 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -986,15 +986,37 @@ struct GPU_PBVH_Buffers {
float diffuse_color[4];
};
-typedef struct {
+static struct {
uint pos, nor, col;
-} VertexBufferAttrID;
+} g_vbo_id = {0};
-static void gpu_pbvh_vert_format_init__gwn(Gwn_VertFormat *format, VertexBufferAttrID *vbo_id)
+/* Allocates a non-initialized buffer to be sent to GPU.
+ * Return is false it indicates that the memory map failed. */
+static bool gpu_pbvh_vert_buf_data_set(GPU_PBVH_Buffers *buffers, unsigned int vert_ct)
{
- vbo_id->pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- vbo_id->nor = GWN_vertformat_attr_add(format, "nor", GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
- vbo_id->col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ if (buffers->vert_buf == NULL) {
+ /* Initialize vertex buffer */
+ /* match 'VertexBufferFormat' */
+
+ static Gwn_VertFormat format = {0};
+ if (format.attrib_ct == 0) {
+ g_vbo_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ g_vbo_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ g_vbo_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ }
+#if 0
+ buffers->vert_buf = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_DYNAMIC);
+ GWN_vertbuf_data_alloc(buffers->vert_buf, vert_ct);
+ }
+ else if (vert_ct != buffers->vert_buf->vertex_ct) {
+ GWN_vertbuf_data_resize(buffers->vert_buf, vert_ct);
+ }
+#else
+ buffers->vert_buf = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STATIC);
+ }
+ GWN_vertbuf_data_alloc(buffers->vert_buf, vert_ct);
+#endif
+ return buffers->vert_buf->data != NULL;
}
static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers)
@@ -1004,14 +1026,14 @@ static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers)
GWN_vertbuf_use(buffers->vert_buf);
}
- GWN_BATCH_DISCARD_SAFE(buffers->triangles);
- buffers->triangles = GWN_batch_create(
- GWN_PRIM_TRIS, buffers->vert_buf,
- /* can be NULL */
- buffers->index_buf);
+ if (buffers->triangles == NULL) {
+ buffers->triangles = GWN_batch_create(
+ GWN_PRIM_TRIS, buffers->vert_buf,
+ /* can be NULL */
+ buffers->index_buf);
+ }
- GWN_BATCH_DISCARD_SAFE(buffers->triangles_fast);
- if (buffers->index_buf_fast) {
+ if ((buffers->triangles_fast == NULL) && buffers->index_buf_fast) {
buffers->triangles_fast = GWN_batch_create(
GWN_PRIM_TRIS, buffers->vert_buf,
/* can be NULL */
@@ -1085,25 +1107,15 @@ void GPU_pbvh_mesh_buffers_update(
rgba_float_to_uchar(diffuse_color_ub, diffuse_color);
/* Build VBO */
- GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
-
- /* match 'VertexBufferFormat' */
- Gwn_VertFormat format = {0};
- VertexBufferAttrID vbo_id;
- gpu_pbvh_vert_format_init__gwn(&format, &vbo_id);
-
- buffers->vert_buf = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(buffers->vert_buf, totelem);
-
- if (buffers->vert_buf->data) {
+ if (gpu_pbvh_vert_buf_data_set(buffers, totelem)) {
/* Vertex data is shared if smooth-shaded, but separate
* copies are made for flat shading because normals
* shouldn't be shared. */
if (buffers->smooth) {
for (uint i = 0; i < totvert; ++i) {
const MVert *v = &mvert[vert_indices[i]];
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.pos, i, v->co);
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.nor, i, v->no);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, i, v->co);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, i, v->no);
}
for (uint i = 0; i < buffers->face_indices_len; i++) {
@@ -1114,10 +1126,10 @@ void GPU_pbvh_mesh_buffers_update(
int v_index = buffers->mloop[lt->tri[j]].v;
uchar color_ub[3];
gpu_color_from_mask_copy(vmask[v_index], diffuse_color, color_ub);
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.col, vidx, color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vidx, color_ub);
}
else {
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.col, vidx, diffuse_color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vidx, diffuse_color_ub);
}
}
}
@@ -1160,9 +1172,9 @@ void GPU_pbvh_mesh_buffers_update(
for (uint j = 0; j < 3; j++) {
const MVert *v = &mvert[vtri[j]];
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.pos, vbo_index, v->co);
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.nor, vbo_index, no);
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.col, vbo_index, color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, v->co);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
vbo_index++;
}
@@ -1171,9 +1183,6 @@ void GPU_pbvh_mesh_buffers_update(
gpu_pbvh_batch_init(buffers);
}
- else {
- GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
- }
}
buffers->mvert = mvert;
@@ -1293,17 +1302,9 @@ void GPU_pbvh_grid_buffers_update(
copy_v4_v4(buffers->diffuse_color, diffuse_color);
- Gwn_VertFormat format = {0};
- VertexBufferAttrID vbo_id;
- gpu_pbvh_vert_format_init__gwn(&format, &vbo_id);
-
- /* Build coord/normal VBO */
- GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
- buffers->vert_buf = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(buffers->vert_buf, totgrid * key->grid_area);
-
uint vbo_index_offset = 0;
- if (buffers->vert_buf->data) {
+ /* Build VBO */
+ if (gpu_pbvh_vert_buf_data_set(buffers, totgrid * key->grid_area)) {
for (i = 0; i < totgrid; ++i) {
CCGElem *grid = grids[grid_indices[i]];
int vbo_index = vbo_index_offset;
@@ -1311,12 +1312,12 @@ void GPU_pbvh_grid_buffers_update(
for (y = 0; y < key->grid_size; y++) {
for (x = 0; x < key->grid_size; x++) {
CCGElem *elem = CCG_grid_elem(key, grid, x, y);
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.pos, vbo_index, CCG_elem_co(key, elem));
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, CCG_elem_co(key, elem));
if (buffers->smooth) {
short no_short[3];
normal_float_to_short_v3(no_short, CCG_elem_no(key, elem));
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.nor, vbo_index, no_short);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short);
if (has_mask) {
uchar color_ub[3];
@@ -1327,7 +1328,7 @@ void GPU_pbvh_grid_buffers_update(
else {
F3TOCHAR3(diffuse_color, color_ub);
}
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.col, vbo_index, color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
}
}
vbo_index += 1;
@@ -1354,7 +1355,7 @@ void GPU_pbvh_grid_buffers_update(
vbo_index = vbo_index_offset + ((j + 1) * key->grid_size + k);
short no_short[3];
normal_float_to_short_v3(no_short, fno);
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.nor, vbo_index, no_short);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short);
if (has_mask) {
uchar color_ub[3];
@@ -1370,7 +1371,7 @@ void GPU_pbvh_grid_buffers_update(
else {
F3TOCHAR3(diffuse_color, color_ub);
}
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.col, vbo_index, color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
}
}
}
@@ -1381,9 +1382,6 @@ void GPU_pbvh_grid_buffers_update(
gpu_pbvh_batch_init(buffers);
}
- else {
- GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
- }
}
buffers->grids = grids;
@@ -1562,7 +1560,6 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
static void gpu_bmesh_vert_to_buffer_copy__gwn(
BMVert *v,
Gwn_VertBuf *vert_buf,
- const VertexBufferAttrID *vbo_id,
int *v_index,
const float fno[3],
const float *fmask,
@@ -1573,12 +1570,12 @@ static void gpu_bmesh_vert_to_buffer_copy__gwn(
if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
/* Set coord, normal, and mask */
- GWN_vertbuf_attr_set(vert_buf, vbo_id->pos, *v_index, v->co);
+ GWN_vertbuf_attr_set(vert_buf, g_vbo_id.pos, *v_index, v->co);
{
short no_short[3];
normal_float_to_short_v3(no_short, fno ? fno : v->no);
- GWN_vertbuf_attr_set(vert_buf, vbo_id->nor, *v_index, no_short);
+ GWN_vertbuf_attr_set(vert_buf, g_vbo_id.nor, *v_index, no_short);
}
{
@@ -1596,7 +1593,7 @@ static void gpu_bmesh_vert_to_buffer_copy__gwn(
effective_mask,
diffuse_color,
color_ub);
- GWN_vertbuf_attr_set(vert_buf, vbo_id->col, *v_index, color_ub);
+ GWN_vertbuf_attr_set(vert_buf, g_vbo_id.col, *v_index, color_ub);
}
/* Assign index for use in the triangle index buffer */
@@ -1694,18 +1691,8 @@ void GPU_pbvh_bmesh_buffers_update(
copy_v4_v4(buffers->diffuse_color, diffuse_color);
- /* Initialize vertex buffer */
- GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
- /* match 'VertexBufferFormat' */
- Gwn_VertFormat format = {0};
- VertexBufferAttrID vbo_id;
- gpu_pbvh_vert_format_init__gwn(&format, &vbo_id);
-
- buffers->vert_buf = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(buffers->vert_buf, totvert);
-
/* Fill vertex buffer */
- if (buffers->vert_buf->data) {
+ if (gpu_pbvh_vert_buf_data_set(buffers, totvert)) {
int v_index = 0;
if (buffers->smooth) {
@@ -1718,7 +1705,7 @@ void GPU_pbvh_bmesh_buffers_update(
GSET_ITER (gs_iter, bm_unique_verts) {
gpu_bmesh_vert_to_buffer_copy__gwn(
BLI_gsetIterator_getKey(&gs_iter),
- buffers->vert_buf, &vbo_id, &v_index, NULL, NULL,
+ buffers->vert_buf, &v_index, NULL, NULL,
cd_vert_mask_offset, diffuse_color,
show_mask);
}
@@ -1726,7 +1713,7 @@ void GPU_pbvh_bmesh_buffers_update(
GSET_ITER (gs_iter, bm_other_verts) {
gpu_bmesh_vert_to_buffer_copy__gwn(
BLI_gsetIterator_getKey(&gs_iter),
- buffers->vert_buf, &vbo_id, &v_index, NULL, NULL,
+ buffers->vert_buf, &v_index, NULL, NULL,
cd_vert_mask_offset, diffuse_color,
show_mask);
}
@@ -1759,7 +1746,7 @@ void GPU_pbvh_bmesh_buffers_update(
for (i = 0; i < 3; i++) {
gpu_bmesh_vert_to_buffer_copy__gwn(
- v[i], buffers->vert_buf, &vbo_id,
+ v[i], buffers->vert_buf,
&v_index, f->no, &fmask,
cd_vert_mask_offset, diffuse_color,
show_mask);
@@ -1774,7 +1761,6 @@ void GPU_pbvh_bmesh_buffers_update(
bm->elem_index_dirty |= BM_VERT;
}
else {
- GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
/* Memory map failed */
return;
}
@@ -1786,9 +1772,6 @@ void GPU_pbvh_bmesh_buffers_update(
GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tottri, maxvert);
/* Initialize triangle index buffer */
- if (buffers->triangles && !buffers->is_index_buf_global) {
- GWN_BATCH_DISCARD_SAFE(buffers->triangles);
- }
buffers->is_index_buf_global = false;
/* Fill triangle index buffer */
@@ -1812,7 +1795,12 @@ void GPU_pbvh_bmesh_buffers_update(
buffers->tot_tri = tottri;
- buffers->index_buf = GWN_indexbuf_build(&elb);
+ if (buffers->index_buf == NULL) {
+ buffers->index_buf = GWN_indexbuf_build(&elb);
+ }
+ else {
+ GWN_indexbuf_build_in_place(&elb, buffers->index_buf);
+ }
}
}
else if (buffers->index_buf) {
@@ -1901,7 +1889,7 @@ bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces,
}
else if (buffers->use_bmesh) {
/* due to dynamic nature of dyntopo, only get first material */
- if (BLI_gset_size(bm_faces) > 0) {
+ if (BLI_gset_len(bm_faces) > 0) {
GSetIterator gs_iter;
BMFace *f;
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 9e4daa2a036..b245c9a161f 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -39,10 +39,14 @@
#include "DNA_node_types.h"
#include "BLI_blenlib.h"
+#include "BLI_hash_mm2a.h"
+#include "BLI_linklist.h"
#include "BLI_utildefines.h"
#include "BLI_dynstr.h"
#include "BLI_ghash.h"
+#include "PIL_time.h"
+
#include "GPU_extensions.h"
#include "GPU_glew.h"
#include "GPU_material.h"
@@ -64,6 +68,50 @@ 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
+ * using undo/redo AND also allows for GPUPass reuse if the Shader code is the
+ * same for 2 different Materials. Unused GPUPasses are free by Garbage collection.
+ **/
+
+static LinkNode *pass_cache = NULL; /* GPUPass */
+
+static uint32_t gpu_pass_hash(const char *vert, const char *geom, const char *frag, const char *defs)
+{
+ BLI_HashMurmur2A hm2a;
+ BLI_hash_mm2a_init(&hm2a, 0);
+ BLI_hash_mm2a_add(&hm2a, (unsigned char *)frag, strlen(frag));
+ BLI_hash_mm2a_add(&hm2a, (unsigned char *)vert, strlen(vert));
+ if (defs)
+ BLI_hash_mm2a_add(&hm2a, (unsigned char *)defs, strlen(defs));
+ if (geom)
+ BLI_hash_mm2a_add(&hm2a, (unsigned char *)geom, strlen(geom));
+
+ return BLI_hash_mm2a_end(&hm2a);
+}
+
+/* Search by hash then by exact string match. */
+static GPUPass *gpu_pass_cache_lookup(
+ const char *vert, const char *geom, const char *frag, const char *defs, uint32_t hash)
+{
+ for (LinkNode *ln = pass_cache; ln; ln = ln->next) {
+ GPUPass *pass = (GPUPass *)ln->link;
+ if (pass->hash == hash) {
+ /* Note: Could be made faster if that becomes a real bottleneck. */
+ if ((defs != NULL) && (strcmp(pass->defines, defs) != 0)) { /* Pass */ }
+ else if ((geom != NULL) && (strcmp(pass->geometrycode, geom) != 0)) { /* Pass */ }
+ else if ((strcmp(pass->fragmentcode, frag) == 0) &&
+ (strcmp(pass->vertexcode, vert) == 0))
+ {
+ return pass;
+ }
+ }
+ }
+ return NULL;
+}
+
+/* -------------------- GPU Codegen ------------------ */
/* type definitions and constants */
@@ -427,6 +475,8 @@ const char *GPU_builtin_name(GPUBuiltin builtin)
return "sampdensity";
else if (builtin == GPU_VOLUME_FLAME)
return "sampflame";
+ else if (builtin == GPU_VOLUME_TEMPERATURE)
+ return "unftemperature";
else
return "";
}
@@ -1173,15 +1223,13 @@ GPUShader *GPU_pass_shader(GPUPass *pass)
return pass->shader;
}
-static void gpu_nodes_extract_dynamic_inputs_new(GPUPass *pass, ListBase *nodes)
+static void gpu_nodes_extract_dynamic_inputs_new(GPUShader *shader, ListBase *inputs, ListBase *nodes)
{
- GPUShader *shader = pass->shader;
GPUNode *node;
GPUInput *next, *input;
- ListBase *inputs = &pass->inputs;
int extract, z;
- memset(inputs, 0, sizeof(*inputs));
+ BLI_listbase_clear(inputs);
if (!shader)
return;
@@ -1234,15 +1282,13 @@ static void gpu_nodes_extract_dynamic_inputs_new(GPUPass *pass, ListBase *nodes)
GPU_shader_unbind();
}
-static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
+static void gpu_nodes_extract_dynamic_inputs(GPUShader *shader, ListBase *inputs, ListBase *nodes)
{
- GPUShader *shader = pass->shader;
GPUNode *node;
GPUInput *next, *input;
- ListBase *inputs = &pass->inputs;
int extract, z;
- memset(inputs, 0, sizeof(*inputs));
+ BLI_listbase_clear(inputs);
if (!shader)
return;
@@ -1320,11 +1366,10 @@ static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
GPU_shader_unbind();
}
-void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
+void GPU_pass_bind(GPUPass *pass, ListBase *inputs, double time, int mipmap)
{
GPUInput *input;
GPUShader *shader = pass->shader;
- ListBase *inputs = &pass->inputs;
if (!shader)
return;
@@ -1349,11 +1394,10 @@ void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
}
}
-void GPU_pass_update_uniforms(GPUPass *pass)
+void GPU_pass_update_uniforms(GPUPass *pass, ListBase *inputs)
{
GPUInput *input;
GPUShader *shader = pass->shader;
- ListBase *inputs = &pass->inputs;
if (!shader)
return;
@@ -1374,11 +1418,10 @@ void GPU_pass_update_uniforms(GPUPass *pass)
}
}
-void GPU_pass_unbind(GPUPass *pass)
+void GPU_pass_unbind(GPUPass *pass, ListBase *inputs)
{
GPUInput *input;
GPUShader *shader = pass->shader;
- ListBase *inputs = &pass->inputs;
if (!shader)
return;
@@ -1677,7 +1720,7 @@ static void gpu_node_output(GPUNode *node, const GPUType type, GPUNodeLink **lin
BLI_addtail(&node->outputs, output);
}
-static void gpu_inputs_free(ListBase *inputs)
+void GPU_inputs_free(ListBase *inputs)
{
GPUInput *input;
@@ -1695,7 +1738,7 @@ static void gpu_node_free(GPUNode *node)
{
GPUOutput *output;
- gpu_inputs_free(&node->inputs);
+ GPU_inputs_free(&node->inputs);
for (output = node->outputs.first; output; output = output->next)
if (output->link) {
@@ -1718,7 +1761,7 @@ static void gpu_nodes_free(ListBase *nodes)
/* vertex attributes */
-static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
+void GPU_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
{
GPUNode *node;
GPUInput *input;
@@ -1958,16 +2001,20 @@ bool GPU_stack_link(GPUMaterial *material, bNode *bnode, const char *name, GPUNo
totout = 0;
if (in) {
- for (i = 0; in[i].type != GPU_NONE; i++) {
- gpu_node_input_socket(material, bnode, node, &in[i], i);
- totin++;
+ for (i = 0; !in[i].end; i++) {
+ if (in[i].type != GPU_NONE) {
+ gpu_node_input_socket(material, bnode, node, &in[i], i);
+ totin++;
+ }
}
}
if (out) {
- for (i = 0; out[i].type != GPU_NONE; i++) {
- gpu_node_output(node, out[i].type, &out[i].link);
- totout++;
+ for (i = 0; !out[i].end; i++) {
+ if (out[i].type != GPU_NONE) {
+ gpu_node_output(node, out[i].type, &out[i].link);
+ totout++;
+ }
}
}
@@ -2046,7 +2093,7 @@ static void gpu_nodes_tag(GPUNodeLink *link)
gpu_nodes_tag(input->link);
}
-static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
+void GPU_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
{
GPUNode *node, *next;
@@ -2066,79 +2113,83 @@ static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
}
GPUPass *GPU_generate_pass_new(
- struct GPUMaterial *material,
- ListBase *nodes, struct GPUNodeLink *frag_outlink,
- GPUVertexAttribs *attribs,
+ GPUMaterial *material,
+ GPUNodeLink *frag_outlink, struct GPUVertexAttribs *attribs,
+ ListBase *nodes, ListBase *inputs,
const char *vert_code, const char *geom_code,
const char *frag_lib, const char *defines)
{
+ char *vertexcode, *geometrycode, *fragmentcode;
GPUShader *shader;
GPUPass *pass;
- char *vertexgen, *fragmentgen, *tmp;
- char *vertexcode, *geometrycode, *fragmentcode;
/* prune unused nodes */
- gpu_nodes_prune(nodes, frag_outlink);
+ GPU_nodes_prune(nodes, frag_outlink);
- gpu_nodes_get_vertex_attributes(nodes, attribs);
+ GPU_nodes_get_vertex_attributes(nodes, attribs);
- /* generate code and compile with opengl */
- fragmentgen = code_generate_fragment(material, nodes, frag_outlink->output, true);
- vertexgen = code_generate_vertex_new(nodes, vert_code, (geom_code != NULL));
+ /* generate code */
+ char *fragmentgen = code_generate_fragment(material, nodes, frag_outlink->output, true);
+ char *tmp = BLI_strdupcat(frag_lib, glsl_material_library);
- tmp = BLI_strdupcat(frag_lib, glsl_material_library);
+ vertexcode = code_generate_vertex_new(nodes, vert_code, (geom_code != NULL));
+ geometrycode = (geom_code) ? code_generate_geometry_new(nodes, geom_code) : NULL;
fragmentcode = BLI_strdupcat(tmp, fragmentgen);
- vertexcode = BLI_strdup(vertexgen);
-
- if (geom_code) {
- geometrycode = code_generate_geometry_new(nodes, geom_code);
- }
- else {
- geometrycode = NULL;
- }
-
- shader = GPU_shader_create(vertexcode,
- fragmentcode,
- geometrycode,
- NULL,
- defines);
+ MEM_freeN(fragmentgen);
MEM_freeN(tmp);
- /* failed? */
+ /* Cache lookup: Reuse shaders already compiled */
+ uint32_t hash = gpu_pass_hash(vertexcode, geometrycode, fragmentcode, defines);
+ pass = gpu_pass_cache_lookup(vertexcode, geometrycode, fragmentcode, defines, hash);
+ if (pass) {
+ /* Cache hit. Reuse the same GPUPass and GPUShader. */
+ shader = pass->shader;
+ pass->refcount += 1;
+
+ MEM_SAFE_FREE(vertexcode);
+ MEM_SAFE_FREE(fragmentcode);
+ MEM_SAFE_FREE(geometrycode);
+ }
+ else {
+ /* Cache miss. (Re)compile the shader. */
+ shader = GPU_shader_create(vertexcode,
+ fragmentcode,
+ geometrycode,
+ NULL,
+ defines);
+
+ /* We still create a pass even if shader compilation
+ * fails to avoid trying to compile again and again. */
+ pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
+ pass->shader = shader;
+ pass->refcount = 1;
+ pass->hash = hash;
+ pass->vertexcode = vertexcode;
+ pass->fragmentcode = fragmentcode;
+ pass->geometrycode = geometrycode;
+ pass->libcode = glsl_material_library;
+ pass->defines = (defines) ? BLI_strdup(defines) : NULL;
+
+ BLI_linklist_prepend(&pass_cache, pass);
+ }
+
+ /* did compilation failed ? */
if (!shader) {
- if (fragmentcode)
- MEM_freeN(fragmentcode);
- if (vertexcode)
- MEM_freeN(vertexcode);
- if (geometrycode)
- MEM_freeN(geometrycode);
- MEM_freeN(fragmentgen);
- MEM_freeN(vertexgen);
gpu_nodes_free(nodes);
+ /* Pass will not be used. Don't increment refcount. */
+ pass->refcount--;
return NULL;
}
-
- /* create pass */
- pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
- pass->shader = shader;
- pass->fragmentcode = fragmentcode;
- pass->geometrycode = geometrycode;
- pass->vertexcode = vertexcode;
- pass->libcode = glsl_material_library;
-
- /* extract dynamic inputs and throw away nodes */
- gpu_nodes_extract_dynamic_inputs_new(pass, nodes);
- gpu_nodes_free(nodes);
-
- MEM_freeN(fragmentgen);
- MEM_freeN(vertexgen);
-
- return pass;
+ else {
+ gpu_nodes_extract_dynamic_inputs_new(shader, inputs, nodes);
+ return pass;
+ }
}
+/* TODO(fclem) Remove for 2.8 */
GPUPass *GPU_generate_pass(
- ListBase *nodes, GPUNodeLink *outlink,
+ ListBase *nodes, ListBase *inputs, GPUNodeLink *outlink,
GPUVertexAttribs *attribs, int *builtins,
const GPUMatType type, const char *UNUSED(name),
const bool use_opensubdiv,
@@ -2156,9 +2207,9 @@ GPUPass *GPU_generate_pass(
#endif
/* prune unused nodes */
- gpu_nodes_prune(nodes, outlink);
+ GPU_nodes_prune(nodes, outlink);
- gpu_nodes_get_vertex_attributes(nodes, attribs);
+ GPU_nodes_get_vertex_attributes(nodes, attribs);
gpu_nodes_get_builtin_flag(nodes, builtins);
/* generate code and compile with opengl */
@@ -2194,30 +2245,38 @@ GPUPass *GPU_generate_pass(
/* create pass */
pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
-
+ pass->refcount = 1;
pass->shader = shader;
pass->fragmentcode = fragmentcode;
pass->geometrycode = geometrycode;
pass->vertexcode = vertexcode;
pass->libcode = glsl_material_library;
+ BLI_linklist_prepend(&pass_cache, pass);
+
/* extract dynamic inputs and throw away nodes */
- gpu_nodes_extract_dynamic_inputs(pass, nodes);
+ gpu_nodes_extract_dynamic_inputs(shader, inputs, nodes);
gpu_nodes_free(nodes);
return pass;
}
-void GPU_pass_free(GPUPass *pass)
+void GPU_pass_release(GPUPass *pass)
+{
+ BLI_assert(pass->refcount > 0);
+ pass->refcount--;
+}
+
+static void gpu_pass_free(GPUPass *pass)
{
- GPU_shader_free(pass->shader);
- gpu_inputs_free(&pass->inputs);
- if (pass->fragmentcode)
- MEM_freeN(pass->fragmentcode);
- if (pass->geometrycode)
- MEM_freeN(pass->geometrycode);
- if (pass->vertexcode)
- MEM_freeN(pass->vertexcode);
+ BLI_assert(pass->refcount == 0);
+ if (pass->shader) {
+ GPU_shader_free(pass->shader);
+ }
+ MEM_SAFE_FREE(pass->fragmentcode);
+ MEM_SAFE_FREE(pass->geometrycode);
+ MEM_SAFE_FREE(pass->vertexcode);
+ MEM_SAFE_FREE(pass->defines);
MEM_freeN(pass);
}
@@ -2226,3 +2285,34 @@ void GPU_pass_free_nodes(ListBase *nodes)
gpu_nodes_free(nodes);
}
+void GPU_pass_cache_garbage_collect(void)
+{
+ static int lasttime = 0;
+ const int shadercollectrate = 60; /* hardcoded for now. */
+ int ctime = (int)PIL_check_seconds_timer();
+
+ if (ctime < shadercollectrate + lasttime)
+ return;
+
+ lasttime = ctime;
+
+ LinkNode *next, **prev_ln = &pass_cache;
+ for (LinkNode *ln = pass_cache; ln; ln = next) {
+ GPUPass *pass = (GPUPass *)ln->link;
+ next = ln->next;
+ if (pass->refcount == 0) {
+ gpu_pass_free(pass);
+ /* Remove from list */
+ MEM_freeN(ln);
+ *prev_ln = next;
+ }
+ else {
+ prev_ln = &ln->next;
+ }
+ }
+}
+
+void GPU_pass_cache_free(void)
+{
+ BLI_linklist_free(pass_cache, (LinkNodeFreeFP)gpu_pass_free);
+}
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index 14e07a6e012..dab0bc3f8b1 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -157,25 +157,27 @@ typedef struct GPUInput {
} GPUInput;
struct GPUPass {
- ListBase inputs;
struct GPUShader *shader;
char *fragmentcode;
char *geometrycode;
char *vertexcode;
+ char *defines;
const char *libcode;
+ unsigned int refcount; /* Orphaned GPUPasses gets freed by the garbage collector. */
+ uint32_t hash; /* Identity hash generated from all GLSL code. */
};
typedef struct GPUPass GPUPass;
GPUPass *GPU_generate_pass_new(
- struct GPUMaterial *material,
- ListBase *nodes, struct GPUNodeLink *frag_outlink,
- struct GPUVertexAttribs *attribs,
+ GPUMaterial *material,
+ GPUNodeLink *frag_outlink, struct GPUVertexAttribs *attribs,
+ ListBase *nodes, ListBase *inputs,
const char *vert_code, const char *geom_code,
const char *frag_lib, const char *defines);
GPUPass *GPU_generate_pass(
- ListBase *nodes, struct GPUNodeLink *outlink,
+ ListBase *nodes, ListBase *inputs, struct GPUNodeLink *outlink,
struct GPUVertexAttribs *attribs, int *builtin,
const GPUMatType type, const char *name,
const bool use_opensubdiv,
@@ -183,13 +185,18 @@ GPUPass *GPU_generate_pass(
struct GPUShader *GPU_pass_shader(GPUPass *pass);
-void GPU_pass_bind(GPUPass *pass, double time, int mipmap);
-void GPU_pass_update_uniforms(GPUPass *pass);
-void GPU_pass_unbind(GPUPass *pass);
+void GPU_nodes_get_vertex_attributes(ListBase *nodes, struct GPUVertexAttribs *attribs);
+void GPU_nodes_prune(ListBase *nodes, struct GPUNodeLink *outlink);
+
+void GPU_pass_bind(GPUPass *pass, ListBase *inputs, double time, int mipmap);
+void GPU_pass_update_uniforms(GPUPass *pass, ListBase *inputs);
+void GPU_pass_unbind(GPUPass *pass, ListBase *inputs);
-void GPU_pass_free(GPUPass *pass);
+void GPU_pass_release(GPUPass *pass);
void GPU_pass_free_nodes(ListBase *nodes);
+void GPU_inputs_free(ListBase *inputs);
+
void gpu_codegen_init(void);
void gpu_codegen_exit(void);
diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c
deleted file mode 100644
index 3de363cc76e..00000000000
--- a/source/blender/gpu/intern/gpu_compositing.c
+++ /dev/null
@@ -1,1494 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2006 Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Antony Riakiotakis.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/gpu/intern/gpu_compositing.c
- * \ingroup gpu
- *
- * System that manages framebuffer compositing.
- */
-
-#include "BLI_sys_types.h"
-#include "BLI_rect.h"
-#include "BLI_math.h"
-
-#include "BLI_rand.h"
-
-#include "DNA_vec_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_gpu_types.h"
-
-#include "GPU_compositing.h"
-#include "GPU_draw.h"
-#include "GPU_extensions.h"
-#include "GPU_framebuffer.h"
-#include "GPU_glew.h"
-#include "GPU_shader.h"
-#include "GPU_texture.h"
-#include "GPU_batch.h"
-
-#include "MEM_guardedalloc.h"
-
-static const float fullscreencos[4][2] = {{-1.0f, -1.0f}, {1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}};
-static const float fullscreenuvs[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}};
-
-
-/* shader interfaces (legacy GL 2 style, without uniform buffer objects) */
-
-typedef struct {
- int ssao_uniform;
- int ssao_color_uniform;
- int color_uniform;
- int depth_uniform;
- int viewvecs_uniform;
- int ssao_sample_params_uniform;
- int ssao_concentric_tex;
- int ssao_jitter_uniform;
-} GPUSSAOShaderInterface;
-
-typedef struct {
- int invrendertargetdim_uniform;
- int color_uniform;
- int dof_uniform;
- int depth_uniform;
- int viewvecs_uniform;
-} GPUDOFHQPassOneInterface;
-
-typedef struct {
- int rendertargetdim_uniform;
- int color_uniform;
- int coc_uniform;
- int select_uniform;
- int dof_uniform;
-} GPUDOFHQPassTwoInterface;
-
-typedef struct {
- int dof_uniform;
- int invrendertargetdim_uniform;
- int color_uniform;
- int far_uniform;
- int near_uniform;
- int viewvecs_uniform;
- int depth_uniform;
-} GPUDOFHQPassThreeInterface;
-
-typedef struct {
- int dof_uniform;
- int invrendertargetdim_uniform;
- int color_uniform;
- int depth_uniform;
- int viewvecs_uniform;
-} GPUDOFPassOneInterface;
-
-typedef struct {
- int dof_uniform;
- int invrendertargetdim_uniform;
- int color_uniform;
- int depth_uniform;
- int viewvecs_uniform;
-} GPUDOFPassTwoInterface;
-
-typedef struct {
- int near_coc_downsampled;
- int near_coc_blurred;
-} GPUDOFPassThreeInterface;
-
-typedef struct {
- int near_coc_downsampled;
- int invrendertargetdim_uniform;
-} GPUDOFPassFourInterface;
-
-typedef struct {
- int medium_blurred_uniform;
- int high_blurred_uniform;
- int dof_uniform;
- int invrendertargetdim_uniform;
- int original_uniform;
- int depth_uniform;
- int viewvecs_uniform;
-} GPUDOFPassFiveInterface;
-
-typedef struct {
- int depth_uniform;
-} GPUDepthResolveInterface;
-
-
-struct GPUFX {
- /* we borrow the term gbuffer from deferred rendering however this is just a regular
- * depth/color framebuffer. Could be extended later though */
- GPUFrameBuffer *gbuffer;
-
- /* dimensions of the gbuffer */
- int gbuffer_dim[2];
-
- /* texture bound to the first color attachment of the gbuffer */
- GPUTexture *color_buffer;
-
- /* second texture used for ping-pong compositing */
- GPUTexture *color_buffer_sec;
- /* texture bound to the depth attachment of the gbuffer */
- GPUTexture *depth_buffer;
- GPUTexture *depth_buffer_xray;
-
- /* texture used for jittering for various effects */
- GPUTexture *jitter_buffer;
-
- /* all those buffers below have to coexist.
- * Fortunately they are all quarter sized (1/16th of memory) of original framebuffer */
- int dof_downsampled_w;
- int dof_downsampled_h;
-
- /* texture used for near coc and color blurring calculation */
- GPUTexture *dof_near_coc_buffer;
- /* blurred near coc buffer. */
- GPUTexture *dof_near_coc_blurred_buffer;
- /* final near coc buffer. */
- GPUTexture *dof_near_coc_final_buffer;
-
- /* half size blur buffer */
- GPUTexture *dof_half_downsampled_near;
- GPUTexture *dof_half_downsampled_far;
- /* high quality dof texture downsamplers. 6 levels means 64 pixels wide - should be enough */
- GPUTexture *dof_nearfar_coc;
- GPUTexture *dof_near_blur;
- GPUTexture *dof_far_blur;
-
- /* for high quality we use again a spiral texture with radius adapted */
- bool dof_high_quality;
-
- /* texture used for ssao */
- int ssao_sample_count_cache;
- GPUTexture *ssao_spiral_samples_tex;
-
-
- GPUFXSettings settings;
-
- /* or-ed flags of enabled effects */
- int effects;
-
- /* number of passes, needed to detect if ping pong buffer allocation is needed */
- int num_passes;
-
- /* we have a stencil, restore the previous state */
- bool restore_stencil;
-
- Gwn_Batch *quad_batch;
- Gwn_Batch *point_batch;
-};
-
-#if 0
-/* concentric mapping, see "A Low Distortion Map Between Disk and Square" and
- * http://psgraphics.blogspot.nl/2011/01/improved-code-for-concentric-map.html */
-static GPUTexture * create_concentric_sample_texture(int side)
-{
- GPUTexture *tex;
- float midpoint = 0.5f * (side - 1);
- float *texels = (float *)MEM_mallocN(sizeof(float) * 2 * side * side, "concentric_tex");
- int i, j;
-
- for (i = 0; i < side; i++) {
- for (j = 0; j < side; j++) {
- int index = (i * side + j) * 2;
- float a = 1.0f - i / midpoint;
- float b = 1.0f - j / midpoint;
- float phi, r;
- if (a * a > b * b) {
- r = a;
- phi = (M_PI_4) * (b / a);
- }
- else {
- r = b;
- phi = M_PI_2 - (M_PI_4) * (a / b);
- }
- texels[index] = r * cos(phi);
- texels[index + 1] = r * sin(phi);
- }
- }
-
- tex = GPU_texture_create_1D_custom(side * side, 2, GPU_RG16F, (float *)texels, NULL);
-
- /* Set parameters */
- GPU_texture_bind(tex, 0);
- GPU_texture_filter_mode(tex, false);
- GPU_texture_unbind(tex);
-
- MEM_freeN(texels);
- return tex;
-}
-#endif
-
-static GPUTexture *create_spiral_sample_texture(int numsaples)
-{
- GPUTexture *tex;
- float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * numsaples, "concentric_tex");
- const float numsaples_inv = 1.0f / numsaples;
- int i;
- /* arbitrary number to ensure we don't get conciding samples every circle */
- const float spirals = 7.357;
-
- for (i = 0; i < numsaples; i++) {
- float r = (i + 0.5f) * numsaples_inv;
- float phi = r * spirals * (float)(2.0 * M_PI);
- texels[i][0] = r * cosf(phi);
- texels[i][1] = r * sinf(phi);
- }
-
- tex = GPU_texture_create_1D_custom(numsaples, 2, GPU_RG16F, (float *)texels, NULL);
-
- /* Set parameters */
- GPU_texture_bind(tex, 0);
- GPU_texture_filter_mode(tex, false);
- GPU_texture_unbind(tex);
-
- MEM_freeN(texels);
- return tex;
-}
-
-/* generate a new FX compositor */
-GPUFX *GPU_fx_compositor_create(void)
-{
- GPUFX *fx = MEM_callocN(sizeof(GPUFX), "GPUFX compositor");
-
- /* Quad buffer */
- static Gwn_VertFormat format = {0};
- static unsigned int pos, uvs;
- if (format.attrib_ct == 0) {
- pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uvs = GWN_vertformat_attr_add(&format, "uvs", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- }
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 4);
- for (int i = 0; i < 4; ++i) {
- GWN_vertbuf_attr_set(vbo, pos, i, fullscreencos[i]);
- GWN_vertbuf_attr_set(vbo, uvs, i, fullscreenuvs[i]);
- }
- fx->quad_batch = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
-
- /* Point Buffer */
- static Gwn_VertFormat format_point = {0};
- static unsigned int dummy_attrib;
- if (format_point.attrib_ct == 0) {
- dummy_attrib = GWN_vertformat_attr_add(&format_point, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- }
- float dummy[2] = {0.0f, 0.0f};
- Gwn_VertBuf *vbo_point = GWN_vertbuf_create_with_format(&format_point);
- GWN_vertbuf_data_alloc(vbo_point, 1);
- GWN_vertbuf_attr_set(vbo_point, dummy_attrib, 0, &dummy);
- fx->point_batch = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo_point, NULL, GWN_BATCH_OWNS_VBO);
-
- return fx;
-}
-
-static void cleanup_fx_dof_buffers(GPUFX *fx)
-{
- if (fx->dof_near_coc_blurred_buffer) {
- GPU_texture_free(fx->dof_near_coc_blurred_buffer);
- fx->dof_near_coc_blurred_buffer = NULL;
- }
- if (fx->dof_near_coc_buffer) {
- GPU_texture_free(fx->dof_near_coc_buffer);
- fx->dof_near_coc_buffer = NULL;
- }
- if (fx->dof_near_coc_final_buffer) {
- GPU_texture_free(fx->dof_near_coc_final_buffer);
- fx->dof_near_coc_final_buffer = NULL;
- }
-
- if (fx->dof_half_downsampled_near) {
- GPU_texture_free(fx->dof_half_downsampled_near);
- fx->dof_half_downsampled_near = NULL;
- }
- if (fx->dof_half_downsampled_far) {
- GPU_texture_free(fx->dof_half_downsampled_far);
- fx->dof_half_downsampled_far = NULL;
- }
- if (fx->dof_nearfar_coc) {
- GPU_texture_free(fx->dof_nearfar_coc);
- fx->dof_nearfar_coc = NULL;
- }
- if (fx->dof_near_blur) {
- GPU_texture_free(fx->dof_near_blur);
- fx->dof_near_blur = NULL;
- }
- if (fx->dof_far_blur) {
- GPU_texture_free(fx->dof_far_blur);
- fx->dof_far_blur = NULL;
- }
-}
-
-static void cleanup_fx_gl_data(GPUFX *fx, bool do_fbo)
-{
- if (fx->color_buffer) {
- GPU_framebuffer_texture_detach(fx->color_buffer);
- GPU_texture_free(fx->color_buffer);
- fx->color_buffer = NULL;
- }
-
- if (fx->color_buffer_sec) {
- GPU_framebuffer_texture_detach(fx->color_buffer_sec);
- GPU_texture_free(fx->color_buffer_sec);
- fx->color_buffer_sec = NULL;
- }
-
- if (fx->depth_buffer) {
- GPU_framebuffer_texture_detach(fx->depth_buffer);
- GPU_texture_free(fx->depth_buffer);
- fx->depth_buffer = NULL;
- }
-
- if (fx->depth_buffer_xray) {
- GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
- GPU_texture_free(fx->depth_buffer_xray);
- fx->depth_buffer_xray = NULL;
- }
-
- cleanup_fx_dof_buffers(fx);
-
- if (fx->ssao_spiral_samples_tex) {
- GPU_texture_free(fx->ssao_spiral_samples_tex);
- fx->ssao_spiral_samples_tex = NULL;
- }
-
- if (fx->jitter_buffer && do_fbo) {
- GPU_texture_free(fx->jitter_buffer);
- fx->jitter_buffer = NULL;
- }
-
- if (fx->gbuffer && do_fbo) {
- GPU_framebuffer_free(fx->gbuffer);
- fx->gbuffer = NULL;
- }
-}
-
-/* destroy a text compositor */
-void GPU_fx_compositor_destroy(GPUFX *fx)
-{
- cleanup_fx_gl_data(fx, true);
- GWN_batch_discard(fx->quad_batch);
- GWN_batch_discard(fx->point_batch);
- MEM_freeN(fx);
-}
-
-static GPUTexture * create_jitter_texture(void)
-{
- GPUTexture *tex;
- float jitter[64 * 64][2];
- int i;
-
- for (i = 0; i < 64 * 64; i++) {
- jitter[i][0] = 2.0f * BLI_frand() - 1.0f;
- jitter[i][1] = 2.0f * BLI_frand() - 1.0f;
- normalize_v2(jitter[i]);
- }
-
- tex = GPU_texture_create_2D_custom(64, 64, 2, GPU_RG16F, &jitter[0][0], NULL);
-
- /* Set parameters */
- GPU_texture_bind(tex, 0);
- GPU_texture_filter_mode(tex, false);
- GPU_texture_wrap_mode(tex, true);
- GPU_texture_unbind(tex);
-
- return tex;
-}
-
-
-bool GPU_fx_compositor_initialize_passes(
- GPUFX *fx, const rcti *rect, const rcti *scissor_rect,
- const GPUFXSettings *fx_settings)
-{
- int w = BLI_rcti_size_x(rect), h = BLI_rcti_size_y(rect);
- char err_out[256];
- int num_passes = 0;
- char fx_flag;
-
- fx->effects = 0;
-
- if (!fx_settings) {
- cleanup_fx_gl_data(fx, true);
- return false;
- }
-
- fx_flag = fx_settings->fx_flag;
-
- /* disable effects if no options passed for them */
- if (!fx_settings->dof) {
- fx_flag &= ~GPU_FX_FLAG_DOF;
- }
- if (!fx_settings->ssao || fx_settings->ssao->samples < 1) {
- fx_flag &= ~GPU_FX_FLAG_SSAO;
- }
-
- if (!fx_flag) {
- cleanup_fx_gl_data(fx, true);
- return false;
- }
-
- /* scissor is missing when drawing offscreen, in that case, dimensions match exactly. In opposite case
- * add one to match viewport dimensions */
- if (scissor_rect) {
- w++;
- h++;
- }
-
- fx->num_passes = 0;
- /* dof really needs a ping-pong buffer to work */
- if (fx_flag & GPU_FX_FLAG_DOF)
- num_passes++;
-
- if (fx_flag & GPU_FX_FLAG_SSAO)
- num_passes++;
-
- if (!fx->gbuffer) {
- fx->gbuffer = GPU_framebuffer_create();
-
- if (!fx->gbuffer) {
- return false;
- }
- }
-
- /* try creating the jitter texture */
- if (!fx->jitter_buffer)
- fx->jitter_buffer = create_jitter_texture();
-
- /* check if color buffers need recreation */
- if (!fx->color_buffer || !fx->depth_buffer || w != fx->gbuffer_dim[0] || h != fx->gbuffer_dim[1]) {
- cleanup_fx_gl_data(fx, false);
-
- if (!(fx->color_buffer = GPU_texture_create_2D(w, h, NULL, err_out))) {
- printf(".256%s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
-
- if (!(fx->depth_buffer = GPU_texture_create_depth(w, h, err_out))) {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- }
-
- if (fx_flag & GPU_FX_FLAG_SSAO) {
- if (fx_settings->ssao->samples != fx->ssao_sample_count_cache || !fx->ssao_spiral_samples_tex) {
- if (fx_settings->ssao->samples < 1)
- fx_settings->ssao->samples = 1;
-
- fx->ssao_sample_count_cache = fx_settings->ssao->samples;
-
- if (fx->ssao_spiral_samples_tex) {
- GPU_texture_free(fx->ssao_spiral_samples_tex);
- }
-
- fx->ssao_spiral_samples_tex = create_spiral_sample_texture(fx_settings->ssao->samples);
- }
- }
- else {
- if (fx->ssao_spiral_samples_tex) {
- GPU_texture_free(fx->ssao_spiral_samples_tex);
- fx->ssao_spiral_samples_tex = NULL;
- }
- }
-
- /* create textures for dof effect */
- if (fx_flag & GPU_FX_FLAG_DOF) {
- bool dof_high_quality = (fx_settings->dof->high_quality != 0);
-
- /* cleanup buffers if quality setting has changed (no need to keep more buffers around than necessary ) */
- if (dof_high_quality != fx->dof_high_quality)
- cleanup_fx_dof_buffers(fx);
-
- if (dof_high_quality) {
- fx->dof_downsampled_w = w / 2;
- fx->dof_downsampled_h = h / 2;
-
- if (!fx->dof_half_downsampled_near || !fx->dof_nearfar_coc || !fx->dof_near_blur ||
- !fx->dof_far_blur || !fx->dof_half_downsampled_far)
- {
-
- if (!(fx->dof_half_downsampled_near = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- if (!(fx->dof_half_downsampled_far = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
-
- if (!(fx->dof_nearfar_coc = GPU_texture_create_2D_custom(
- fx->dof_downsampled_w, fx->dof_downsampled_h, 2, GPU_RG16F, NULL, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- GPU_texture_bind(fx->dof_nearfar_coc, 0);
- GPU_texture_filter_mode(fx->dof_nearfar_coc, false);
- GPU_texture_wrap_mode(fx->dof_nearfar_coc, false);
- GPU_texture_unbind(fx->dof_nearfar_coc);
-
- if (!(fx->dof_near_blur = GPU_texture_create_2D_custom(
- fx->dof_downsampled_w, fx->dof_downsampled_h, 4, GPU_RGBA16F, NULL, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
-
- if (!(fx->dof_far_blur = GPU_texture_create_2D_custom(
- fx->dof_downsampled_w, fx->dof_downsampled_h, 4, GPU_RGBA16F, NULL, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- }
- }
- else {
- fx->dof_downsampled_w = w / 4;
- fx->dof_downsampled_h = h / 4;
-
- if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) {
-
- if (!(fx->dof_near_coc_buffer = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- if (!(fx->dof_near_coc_blurred_buffer = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- if (!(fx->dof_near_coc_final_buffer = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- }
- }
-
- fx->dof_high_quality = dof_high_quality;
- }
- else {
- /* cleanup unnecessary buffers */
- cleanup_fx_dof_buffers(fx);
- }
-
- /* we need to pass data between shader stages, allocate an extra color buffer */
- if (num_passes > 1) {
- if (!fx->color_buffer_sec) {
- if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, err_out))) {
- printf(".256%s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- }
- }
- else {
- if (fx->color_buffer_sec) {
- GPU_framebuffer_texture_detach(fx->color_buffer_sec);
- GPU_texture_free(fx->color_buffer_sec);
- fx->color_buffer_sec = NULL;
- }
- }
-
- /* bind the buffers */
-
- /* first depth buffer, because system assumes read/write buffers */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, 0);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0, 0);
-
- if (!GPU_framebuffer_check_valid(fx->gbuffer, err_out))
- printf("%.256s\n", err_out);
-
- GPU_texture_bind_as_framebuffer(fx->color_buffer);
-
- /* enable scissor test. It's needed to ensure sculpting works correctly */
- if (scissor_rect) {
- int w_sc = BLI_rcti_size_x(scissor_rect) + 1;
- int h_sc = BLI_rcti_size_y(scissor_rect) + 1;
- gpuPushAttrib(GPU_SCISSOR_BIT);
- glEnable(GL_SCISSOR_TEST);
- glScissor(scissor_rect->xmin - rect->xmin, scissor_rect->ymin - rect->ymin,
- w_sc, h_sc);
- fx->restore_stencil = true;
- }
- else {
- fx->restore_stencil = false;
- }
-
- fx->effects = fx_flag;
-
- if (fx_settings)
- fx->settings = *fx_settings;
- fx->gbuffer_dim[0] = w;
- fx->gbuffer_dim[1] = h;
-
- fx->num_passes = num_passes;
-
- return true;
-}
-
-static void gpu_fx_bind_render_target(int *passes_left, GPUFX *fx, struct GPUOffScreen *ofs, GPUTexture *target)
-{
- if ((*passes_left)-- == 1) {
- GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
- if (ofs) {
- GPU_offscreen_bind(ofs, false);
- }
- else
- GPU_framebuffer_restore();
- }
- else {
- /* bind the ping buffer to the color buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, target, 0, 0);
- }
-}
-
-void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray)
-{
- char err_out[256];
-
- if (do_xray) {
- if (!fx->depth_buffer_xray &&
- !(fx->depth_buffer_xray = GPU_texture_create_depth(fx->gbuffer_dim[0], fx->gbuffer_dim[1], err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return;
- }
- }
- else {
- if (fx->depth_buffer_xray) {
- GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
- GPU_texture_free(fx->depth_buffer_xray);
- fx->depth_buffer_xray = NULL;
- }
- return;
- }
-
- GPU_framebuffer_texture_detach(fx->depth_buffer);
-
- /* first depth buffer, because system assumes read/write buffers */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer_xray, 0, 0);
-}
-
-
-void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
-{
- GPUShader *depth_resolve_shader;
- GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
-
- /* attach regular framebuffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, 0);
-
- /* full screen quad where we will always write to depth buffer */
- gpuPushAttrib(GPU_DEPTH_BUFFER_BIT | GPU_SCISSOR_BIT);
- glDepthFunc(GL_ALWAYS);
- /* disable scissor from sculpt if any */
- glDisable(GL_SCISSOR_TEST);
- /* disable writing to color buffer, it's depth only pass */
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-
- depth_resolve_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_RESOLVE, false);
-
- if (depth_resolve_shader) {
- GPUDepthResolveInterface *interface = GPU_fx_shader_get_interface(depth_resolve_shader);
-
- /* set up quad buffer */
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(depth_resolve_shader), GPU_shader_get_interface(depth_resolve_shader));
-
- GPU_texture_bind(fx->depth_buffer_xray, 0);
- GPU_texture_compare_mode(fx->depth_buffer_xray, false);
- GPU_texture_filter_mode(fx->depth_buffer_xray, true);
- GPU_shader_uniform_texture(depth_resolve_shader, interface->depth_uniform, fx->depth_buffer_xray);
-
- /* draw */
- GWN_batch_draw(fx->quad_batch);
-
- /* disable bindings */
- GPU_texture_compare_mode(fx->depth_buffer_xray, true);
- GPU_texture_filter_mode(fx->depth_buffer_xray, false);
- GPU_texture_unbind(fx->depth_buffer_xray);
-
- GPU_shader_unbind();
- }
-
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-
- gpuPopAttrib();
-}
-
-
-bool GPU_fx_do_composite_pass(
- GPUFX *fx, float projmat[4][4], bool is_persp,
- struct Scene *scene, struct GPUOffScreen *ofs)
-{
- GPUTexture *src, *target;
- int numslots = 0;
- float invproj[4][4];
- int i;
- float dfdyfac[2];
- /* number of passes left. when there are no more passes, the result is passed to the frambuffer */
- int passes_left = fx->num_passes;
- /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */
- float viewvecs[3][4] = {
- {-1.0f, -1.0f, -1.0f, 1.0f},
- {1.0f, -1.0f, -1.0f, 1.0f},
- {-1.0f, 1.0f, -1.0f, 1.0f}
- };
-
- if (fx->effects == 0)
- return false;
-
- GPU_get_dfdy_factors(dfdyfac);
- /* first, unbind the render-to-texture framebuffer */
- GPU_framebuffer_texture_detach(fx->color_buffer);
- GPU_framebuffer_texture_detach(fx->depth_buffer);
-
- if (fx->restore_stencil) {
- gpuPopAttrib();
- }
-
- src = fx->color_buffer;
- target = fx->color_buffer_sec;
-
- /* full screen FX pass */
-
- /* invert the view matrix */
- invert_m4_m4(invproj, projmat);
-
- /* convert the view vectors to view space */
- for (i = 0; i < 3; i++) {
- mul_m4_v4(invproj, viewvecs[i]);
- /* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
- mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
- if (is_persp)
- mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
- viewvecs[i][3] = 1.0;
- }
-
- /* we need to store the differences */
- viewvecs[1][0] -= viewvecs[0][0];
- viewvecs[1][1] = viewvecs[2][1] - viewvecs[0][1];
-
- /* calculate a depth offset as well */
- if (!is_persp) {
- float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
- mul_m4_v4(invproj, vec_far);
- mul_v3_fl(vec_far, 1.0f / vec_far[3]);
- viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
- }
-
- glDisable(GL_DEPTH_TEST);
-
- /* ssao pass */
- if (fx->effects & GPU_FX_FLAG_SSAO) {
- GPUShader *ssao_shader;
- ssao_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_SSAO, is_persp);
- if (ssao_shader) {
- const GPUSSAOSettings *fx_ssao = fx->settings.ssao;
- /* adjust attenuation to be scale invariant */
- float attenuation = fx_ssao->attenuation / (fx_ssao->distance_max * fx_ssao->distance_max);
- float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, attenuation, 0.0f};
- float sample_params[3];
-
- sample_params[0] = fx->ssao_sample_count_cache;
- /* multiplier so we tile the random texture on screen */
- sample_params[1] = fx->gbuffer_dim[0] / 64.0;
- sample_params[2] = fx->gbuffer_dim[1] / 64.0;
-
- ssao_params[3] = (passes_left == 1 && !ofs) ? dfdyfac[0] : dfdyfac[1];
-
- GPUSSAOShaderInterface *interface = GPU_fx_shader_get_interface(ssao_shader);
-
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(ssao_shader), GPU_shader_get_interface(ssao_shader));
-
- GPU_shader_uniform_vector(ssao_shader, interface->ssao_uniform, 4, 1, ssao_params);
- GPU_shader_uniform_vector(ssao_shader, interface->ssao_color_uniform, 4, 1, fx_ssao->color);
- GPU_shader_uniform_vector(ssao_shader, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
- GPU_shader_uniform_vector(ssao_shader, interface->ssao_sample_params_uniform, 3, 1, sample_params);
-
- GPU_texture_bind(src, numslots++);
- GPU_shader_uniform_texture(ssao_shader, interface->color_uniform, src);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_compare_mode(fx->depth_buffer, false);
- GPU_texture_filter_mode(fx->depth_buffer, true);
- GPU_shader_uniform_texture(ssao_shader, interface->depth_uniform, fx->depth_buffer);
-
- GPU_texture_bind(fx->jitter_buffer, numslots++);
- GPU_shader_uniform_texture(ssao_shader, interface->ssao_jitter_uniform, fx->jitter_buffer);
-
- GPU_texture_bind(fx->ssao_spiral_samples_tex, numslots++);
- GPU_shader_uniform_texture(ssao_shader, interface->ssao_concentric_tex, fx->ssao_spiral_samples_tex);
-
- /* draw */
- gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
-
- GWN_batch_draw(fx->quad_batch);
-
- /* disable bindings */
- GPU_texture_unbind(src);
- GPU_texture_compare_mode(fx->depth_buffer, true);
- GPU_texture_filter_mode(fx->depth_buffer, false);
- GPU_texture_unbind(fx->depth_buffer);
- GPU_texture_unbind(fx->jitter_buffer);
- GPU_texture_unbind(fx->ssao_spiral_samples_tex);
-
- /* may not be attached, in that case this just returns */
- if (target) {
- GPU_framebuffer_texture_detach(target);
- if (ofs) {
- GPU_offscreen_bind(ofs, false);
- }
- else {
- GPU_framebuffer_restore();
- }
- }
-
- /* swap here, after src/target have been unbound */
- SWAP(GPUTexture *, target, src);
- numslots = 0;
- }
- }
-
- /* second pass, dof */
- if (fx->effects & GPU_FX_FLAG_DOF) {
- const GPUDOFSettings *fx_dof = fx->settings.dof;
- float dof_params[4];
- float scale = scene->unit.system ? scene->unit.scale_length : 1.0f;
- /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm
- * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though
- * because the shader reads coordinates in world space, which is in blender units.
- * Note however that focus_distance is already in blender units and shall not be scaled here (see T48157). */
- float scale_camera = 0.001f / scale;
- /* we want radius here for the aperture number */
- float aperture = 0.5f * scale_camera * fx_dof->focal_length / fx_dof->fstop;
-
- dof_params[0] = aperture * fabsf(scale_camera * fx_dof->focal_length /
- (fx_dof->focus_distance - scale_camera * fx_dof->focal_length));
- dof_params[1] = fx_dof->focus_distance;
- dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
- dof_params[3] = fx_dof->num_blades;
-
- if (fx->dof_high_quality) {
- GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3;
-
- /* custom shaders close to the effect described in CryEngine 3 Graphics Gems */
- dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE, is_persp);
- dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO, is_persp);
- dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE, is_persp);
-
- /* error occured, restore framebuffers and return */
- if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3)) {
- GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
- GPU_framebuffer_restore();
-
- GPU_shader_unbind();
- return false;
- }
-
- /* pass first, downsample the color buffer to near/far targets and calculate coc texture */
- {
- float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
-
- GPUDOFHQPassOneInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass1);
-
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass1), GPU_shader_get_interface(dof_shader_pass1));
-
- GPU_shader_uniform_vector(dof_shader_pass1, interface->dof_uniform, 4, 1, dof_params);
- GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass1, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
-
- GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_compare_mode(fx->depth_buffer, false);
- GPU_texture_filter_mode(fx->depth_buffer, false);
- GPU_shader_uniform_texture(dof_shader_pass1, interface->depth_uniform, fx->depth_buffer);
-
- GPU_texture_bind(src, numslots++);
- /* disable filtering for the texture so custom downsample can do the right thing */
- GPU_texture_filter_mode(src, false);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, src);
-
- /* target is the downsampled coc buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_near, 0, 0);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_far, 1, 0);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_nearfar_coc, 2, 0);
- /* binding takes care of setting the viewport to the downsampled size */
- GPU_framebuffer_slots_bind(fx->gbuffer, 0);
-
- GPU_framebuffer_check_valid(fx->gbuffer, NULL);
-
- GWN_batch_draw(fx->quad_batch);
-
- /* disable bindings */
- GPU_texture_filter_mode(src, true);
- GPU_texture_unbind(src);
- GPU_texture_compare_mode(fx->depth_buffer, true);
- GPU_texture_filter_mode(fx->depth_buffer, false);
- GPU_texture_unbind(fx->depth_buffer);
-
- GPU_framebuffer_texture_detach(fx->dof_half_downsampled_near);
- GPU_framebuffer_texture_detach(fx->dof_half_downsampled_far);
- GPU_framebuffer_texture_detach(fx->dof_nearfar_coc);
- GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_half_downsampled_near);
-
- numslots = 0;
- }
-
- /* second pass, shoot quads for every pixel in the downsampled buffers, scaling according
- * to circle of confusion */
- {
- int rendertargetdim[2] = {fx->dof_downsampled_w, fx->dof_downsampled_h};
- float selection[2] = {0.0f, 1.0f};
-
- GPUDOFHQPassTwoInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass2);
-
- GWN_batch_program_set(fx->point_batch, GPU_shader_get_program(dof_shader_pass2), GPU_shader_get_interface(dof_shader_pass2));
-
- GPU_texture_bind(fx->dof_nearfar_coc, numslots++);
- GPU_texture_bind(fx->dof_half_downsampled_far, numslots++);
- GPU_texture_bind(fx->dof_half_downsampled_near, numslots++);
-
- GPU_shader_uniform_vector(dof_shader_pass2, interface->dof_uniform, 4, 1, dof_params);
- GPU_shader_uniform_vector_int(dof_shader_pass2, interface->rendertargetdim_uniform, 2, 1, rendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass2, interface->select_uniform, 2, 1, selection);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->coc_uniform, fx->dof_nearfar_coc);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_far);
- GPU_texture_filter_mode(fx->dof_half_downsampled_far, false);
-
- /* target is the downsampled coc buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_far_blur, 0, 0);
- GPU_texture_bind_as_framebuffer(fx->dof_far_blur);
-
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE);
- glPointSize(1.0f);
- /* have to clear the buffer unfortunately */
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
- /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
- GWN_batch_draw_stupid_instanced(fx->point_batch, 0, fx->dof_downsampled_w * fx->dof_downsampled_h, 0, 0, 0, NULL, NULL);
-
- GPU_texture_unbind(fx->dof_half_downsampled_far);
- GPU_framebuffer_texture_detach(fx->dof_far_blur);
-
- selection[0] = 1.0f;
- selection[1] = 0.0f;
-
- GPU_shader_uniform_vector(dof_shader_pass2, interface->select_uniform, 2, 1, selection);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_near);
- GPU_texture_filter_mode(fx->dof_half_downsampled_near, false);
-
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_blur, 0, 0);
- /* have to clear the buffer unfortunately */
- glClear(GL_COLOR_BUFFER_BIT);
- /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
- GWN_batch_draw_stupid_instanced(fx->point_batch, 0, fx->dof_downsampled_w * fx->dof_downsampled_h, 0, 0, 0, NULL, NULL);
- GWN_batch_program_use_end(fx->point_batch);
-
- /* disable bindings */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glDisable(GL_BLEND);
-
- GPU_framebuffer_texture_detach(fx->dof_near_blur);
-
- GPU_texture_unbind(fx->dof_half_downsampled_near);
- GPU_texture_unbind(fx->dof_nearfar_coc);
-
- GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_far_blur);
- numslots = 0;
- }
-
- /* third pass, accumulate the near/far blur fields */
- {
- float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
-
- GPUDOFHQPassThreeInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass3);
-
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass3), GPU_shader_get_interface(dof_shader_pass3));
-
- GPU_shader_uniform_vector(dof_shader_pass3, interface->dof_uniform, 4, 1, dof_params);
-
- GPU_shader_uniform_vector(dof_shader_pass3, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass3, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
-
- GPU_texture_bind(fx->dof_near_blur, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->near_uniform, fx->dof_near_blur);
- GPU_texture_filter_mode(fx->dof_near_blur, true);
-
- GPU_texture_bind(fx->dof_far_blur, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->far_uniform, fx->dof_far_blur);
- GPU_texture_filter_mode(fx->dof_far_blur, true);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_compare_mode(fx->depth_buffer, false);
- GPU_texture_filter_mode(fx->depth_buffer, false);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->depth_uniform, fx->depth_buffer);
-
- GPU_texture_bind(src, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->color_uniform, src);
-
- /* if this is the last pass, prepare for rendering on the frambuffer */
- gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
-
- GWN_batch_draw(fx->quad_batch);
-
- /* disable bindings */
- GPU_texture_unbind(fx->dof_near_blur);
- GPU_texture_unbind(fx->dof_far_blur);
- GPU_texture_unbind(src);
- GPU_texture_compare_mode(fx->depth_buffer, true);
- GPU_texture_unbind(fx->depth_buffer);
-
- /* may not be attached, in that case this just returns */
- if (target) {
- GPU_framebuffer_texture_detach(target);
- if (ofs) {
- GPU_offscreen_bind(ofs, false);
- }
- else {
- GPU_framebuffer_restore();
- }
- }
-
- numslots = 0;
- }
- }
- else {
- GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3, *dof_shader_pass4, *dof_shader_pass5;
-
- /* DOF effect has many passes but most of them are performed
- * on a texture whose dimensions are 4 times less than the original
- * (16 times lower than original screen resolution).
- * Technique used is not very exact but should be fast enough and is based
- * on "Practical Post-Process Depth of Field"
- * see http://http.developer.nvidia.com/GPUGems3/gpugems3_ch28.html */
- dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE, is_persp);
- dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO, is_persp);
- dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE, is_persp);
- dof_shader_pass4 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR, is_persp);
- dof_shader_pass5 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE, is_persp);
-
- /* error occured, restore framebuffers and return */
- if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3 && dof_shader_pass4 && dof_shader_pass5)) {
- GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
- GPU_framebuffer_restore();
-
- GPU_shader_unbind();
- return false;
- }
-
- /* pass first, first level of blur in low res buffer */
- {
- float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
-
- GPUDOFPassOneInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass1);
-
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass1), GPU_shader_get_interface(dof_shader_pass1));
-
- GPU_shader_uniform_vector(dof_shader_pass1, interface->dof_uniform, 4, 1, dof_params);
- GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass1, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
-
- GPU_texture_bind(src, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass1, interface->color_uniform, src);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_compare_mode(fx->depth_buffer, false);
- GPU_texture_filter_mode(fx->depth_buffer, true);
- GPU_shader_uniform_texture(dof_shader_pass1, interface->depth_uniform, fx->depth_buffer);
-
- /* target is the downsampled coc buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, 0);
- /* binding takes care of setting the viewport to the downsampled size */
- GPU_texture_bind_as_framebuffer(fx->dof_near_coc_buffer);
-
- GWN_batch_draw(fx->quad_batch);
- /* disable bindings */
- GPU_texture_unbind(src);
- GPU_texture_compare_mode(fx->depth_buffer, true);
- GPU_texture_filter_mode(fx->depth_buffer, false);
- GPU_texture_unbind(fx->depth_buffer);
-
- GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
- numslots = 0;
- }
-
- /* second pass, gaussian blur the downsampled image */
- {
- float invrendertargetdim[2] = {1.0f / GPU_texture_width(fx->dof_near_coc_blurred_buffer),
- 1.0f / GPU_texture_height(fx->dof_near_coc_blurred_buffer)};
- float tmp = invrendertargetdim[0];
- invrendertargetdim[0] = 0.0f;
-
- GPUDOFPassTwoInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass2);
-
- dof_params[2] = GPU_texture_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor);
-
- /* Blurring vertically */
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass2), GPU_shader_get_interface(dof_shader_pass2));
-
- GPU_shader_uniform_vector(dof_shader_pass2, interface->dof_uniform, 4, 1, dof_params);
- GPU_shader_uniform_vector(dof_shader_pass2, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass2, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_compare_mode(fx->depth_buffer, false);
- GPU_texture_filter_mode(fx->depth_buffer, true);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->depth_uniform, fx->depth_buffer);
-
- GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_near_coc_buffer);
-
- /* use final buffer as a temp here */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, 0);
-
- /* Drawing quad */
- GWN_batch_draw(fx->quad_batch);
-
- /* Rebind Shader */
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass2), GPU_shader_get_interface(dof_shader_pass2));
-
- /* *unbind/detach */
- GPU_texture_unbind(fx->dof_near_coc_buffer);
-
- GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
-
- /* Blurring horizontally */
- invrendertargetdim[0] = tmp;
- invrendertargetdim[1] = 0.0f;
- GPU_shader_uniform_vector(dof_shader_pass2, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
-
- GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_near_coc_final_buffer);
-
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, 0);
-
- GWN_batch_draw(fx->quad_batch);
-
- /* *unbind/detach */
- GPU_texture_compare_mode(fx->depth_buffer, true);
- GPU_texture_filter_mode(fx->depth_buffer, false);
- GPU_texture_unbind(fx->depth_buffer);
-
- GPU_texture_unbind(fx->dof_near_coc_final_buffer);
- GPU_framebuffer_texture_detach(fx->dof_near_coc_blurred_buffer);
-
- dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
-
- numslots = 0;
- }
-
- /* third pass, calculate near coc */
- {
- GPUDOFPassThreeInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass3);
-
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass3), GPU_shader_get_interface(dof_shader_pass3));
-
- GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->near_coc_downsampled, fx->dof_near_coc_buffer);
-
- GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->near_coc_blurred, fx->dof_near_coc_blurred_buffer);
-
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, 0);
-
- GWN_batch_draw(fx->quad_batch);
- /* disable bindings */
- GPU_texture_unbind(fx->dof_near_coc_buffer);
- GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
-
- /* unbinding here restores the size to the original */
- GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
-
- numslots = 0;
- }
-
- /* fourth pass blur final coc once to eliminate discontinuities */
- {
- float invrendertargetdim[2] = {1.0f / GPU_texture_width(fx->dof_near_coc_blurred_buffer),
- 1.0f / GPU_texture_height(fx->dof_near_coc_blurred_buffer)};
-
- GPUDOFPassFourInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass4);
-
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass4), GPU_shader_get_interface(dof_shader_pass4));
-
- GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass4, interface->near_coc_downsampled, fx->dof_near_coc_final_buffer);
- GPU_shader_uniform_vector(dof_shader_pass4, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
-
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, 0);
-
- GWN_batch_draw(fx->quad_batch);
- /* disable bindings */
- GPU_texture_unbind(fx->dof_near_coc_final_buffer);
-
- /* unbinding here restores the size to the original */
- GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_near_coc_buffer);
- GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
-
- numslots = 0;
- }
-
- /* final pass, merge blurred layers according to final calculated coc */
- {
- float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
-
- GPUDOFPassFiveInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass5);
-
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass5), GPU_shader_get_interface(dof_shader_pass5));
-
- GPU_shader_uniform_vector(dof_shader_pass5, interface->dof_uniform, 4, 1, dof_params);
- GPU_shader_uniform_vector(dof_shader_pass5, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass5, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
-
- GPU_texture_bind(src, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass5, interface->original_uniform, src);
-
- GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass5, interface->high_blurred_uniform, fx->dof_near_coc_blurred_buffer);
-
- GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass5, interface->medium_blurred_uniform, fx->dof_near_coc_buffer);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_compare_mode(fx->depth_buffer, false);
- GPU_texture_filter_mode(fx->depth_buffer, true);
- GPU_shader_uniform_texture(dof_shader_pass5, interface->depth_uniform, fx->depth_buffer);
-
- /* if this is the last pass, prepare for rendering on the frambuffer */
- gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
-
- GWN_batch_draw(fx->quad_batch);
- /* disable bindings */
- GPU_texture_unbind(fx->dof_near_coc_buffer);
- GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
- GPU_texture_unbind(src);
- GPU_texture_compare_mode(fx->depth_buffer, true);
- GPU_texture_filter_mode(fx->depth_buffer, false);
- GPU_texture_unbind(fx->depth_buffer);
-
- /* may not be attached, in that case this just returns */
- if (target) {
- GPU_framebuffer_texture_detach(target);
- if (ofs) {
- GPU_offscreen_bind(ofs, false);
- }
- else {
- GPU_framebuffer_restore();
- }
- }
-
- SWAP(GPUTexture *, target, src);
- numslots = 0;
- }
- }
- }
-
- GPU_shader_unbind();
-
- return true;
-}
-
-void GPU_fx_compositor_init_dof_settings(GPUDOFSettings *fx_dof)
-{
- fx_dof->fstop = 128.0f;
- fx_dof->focal_length = 1.0f;
- fx_dof->focus_distance = 1.0f;
- fx_dof->sensor = 1.0f;
- fx_dof->num_blades = 6;
- fx_dof->ratio = 1.0f;
-}
-
-void GPU_fx_compositor_init_ssao_settings(GPUSSAOSettings *fx_ssao)
-{
- fx_ssao->factor = 1.0f;
- fx_ssao->distance_max = 0.2f;
- fx_ssao->attenuation = 1.0f;
- fx_ssao->samples = 20;
-}
-
-void GPU_fx_shader_init_interface(GPUShader *shader, GPUFXShaderEffect effect)
-{
- if (!shader)
- return;
-
- switch (effect) {
- case GPU_SHADER_FX_SSAO:
- {
- GPUSSAOShaderInterface *interface = MEM_mallocN(sizeof(GPUSSAOShaderInterface), "GPUSSAOShaderInterface");
-
- interface->ssao_uniform = GPU_shader_get_uniform(shader, "ssao_params");
- interface->ssao_color_uniform = GPU_shader_get_uniform(shader, "ssao_color");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
- interface->ssao_sample_params_uniform = GPU_shader_get_uniform(shader, "ssao_sample_params");
- interface->ssao_concentric_tex = GPU_shader_get_uniform(shader, "ssao_concentric_tex");
- interface->ssao_jitter_uniform = GPU_shader_get_uniform(shader, "jitter_tex");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
- {
- GPUDOFHQPassOneInterface *interface = MEM_mallocN(sizeof(GPUDOFHQPassOneInterface), "GPUDOFHQPassOneInterface");
-
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
- {
- GPUDOFHQPassTwoInterface *interface = MEM_mallocN(sizeof(GPUDOFHQPassTwoInterface), "GPUDOFHQPassTwoInterface");
-
- interface->rendertargetdim_uniform = GPU_shader_get_uniform(shader, "rendertargetdim");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->coc_uniform = GPU_shader_get_uniform(shader, "cocbuffer");
- interface->select_uniform = GPU_shader_get_uniform(shader, "layerselection");
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
- {
- GPUDOFHQPassThreeInterface *interface = MEM_mallocN(sizeof(GPUDOFHQPassThreeInterface), "GPUDOFHQPassThreeInterface");
-
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->far_uniform = GPU_shader_get_uniform(shader, "farbuffer");
- interface->near_uniform = GPU_shader_get_uniform(shader, "nearbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
- {
- GPUDOFPassOneInterface *interface = MEM_mallocN(sizeof(GPUDOFPassOneInterface), "GPUDOFPassOneInterface");
-
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
- {
- GPUDOFPassTwoInterface *interface = MEM_mallocN(sizeof(GPUDOFPassTwoInterface), "GPUDOFPassTwoInterface");
-
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
- {
- GPUDOFPassThreeInterface *interface = MEM_mallocN(sizeof(GPUDOFPassThreeInterface), "GPUDOFPassThreeInterface");
-
- interface->near_coc_downsampled = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->near_coc_blurred = GPU_shader_get_uniform(shader, "blurredcolorbuffer");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
- {
- GPUDOFPassFourInterface *interface = MEM_mallocN(sizeof(GPUDOFPassFourInterface), "GPUDOFPassFourInterface");
-
- interface->near_coc_downsampled = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
- {
- GPUDOFPassFiveInterface *interface = MEM_mallocN(sizeof(GPUDOFPassFiveInterface), "GPUDOFPassFiveInterface");
-
- interface->medium_blurred_uniform = GPU_shader_get_uniform(shader, "mblurredcolorbuffer");
- interface->high_blurred_uniform = GPU_shader_get_uniform(shader, "blurredcolorbuffer");
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- interface->original_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
-
- case GPU_SHADER_FX_DEPTH_RESOLVE:
- {
- GPUDepthResolveInterface *interface = MEM_mallocN(sizeof(GPUDepthResolveInterface), "GPUDepthResolveInterface");
-
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
-
- default:
- break;
- }
-}
-
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index f9cf3235ac1..8b344716a9c 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -39,11 +39,11 @@
#include <string.h>
#include "BLI_blenlib.h"
+#include "BLI_hash.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLI_hash.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
@@ -398,7 +398,7 @@ static void gpu_set_alpha_blend(GPUBlendMode alphablend)
if (alphablend == GPU_BLEND_SOLID) {
glDisable(GL_BLEND);
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
else if (alphablend == GPU_BLEND_ADD) {
glEnable(GL_BLEND);
@@ -1319,9 +1319,9 @@ static LinkNode *image_free_queue = NULL;
static void gpu_queue_image_for_free(Image *ima)
{
- BLI_lock_thread(LOCK_OPENGL);
+ BLI_thread_lock(LOCK_OPENGL);
BLI_linklist_prepend(&image_free_queue, ima);
- BLI_unlock_thread(LOCK_OPENGL);
+ BLI_thread_unlock(LOCK_OPENGL);
}
void GPU_free_unused_buffers(void)
@@ -1329,7 +1329,7 @@ void GPU_free_unused_buffers(void)
if (!BLI_thread_is_main())
return;
- BLI_lock_thread(LOCK_OPENGL);
+ BLI_thread_lock(LOCK_OPENGL);
/* images */
for (LinkNode *node = image_free_queue; node; node = node->next) {
@@ -1346,7 +1346,7 @@ void GPU_free_unused_buffers(void)
/* vbo buffers */
GPU_global_buffer_pool_free_unused();
- BLI_unlock_thread(LOCK_OPENGL);
+ BLI_thread_unlock(LOCK_OPENGL);
}
void GPU_free_image(Image *ima)
@@ -1734,6 +1734,8 @@ static int gpu_get_particle_info(GPUParticleInfo *pi)
pi->scalprops[3] = p->size;
copy_v3_v3(pi->location, p->state.co);
+ pi->location[3] = BLI_hash_int_01(ind);
+
copy_v3_v3(pi->velocity, p->state.vel);
copy_v3_v3(pi->angular_velocity, p->state.ave);
return 1;
@@ -2093,7 +2095,7 @@ int GPU_scene_object_lights(ViewLayer *view_layer, float viewmat[4][4], int orth
return count;
}
-static void gpu_multisample(bool enable)
+static void gpu_disable_multisample(void)
{
#ifdef __linux__
/* changing multisample from the default (enabled) causes problems on some
@@ -2109,16 +2111,10 @@ static void gpu_multisample(bool enable)
}
if (toggle_ok) {
- if (enable)
- glEnable(GL_MULTISAMPLE);
- else
- glDisable(GL_MULTISAMPLE);
+ glDisable(GL_MULTISAMPLE);
}
#else
- if (enable)
- glEnable(GL_MULTISAMPLE);
- else
- glDisable(GL_MULTISAMPLE);
+ glDisable(GL_MULTISAMPLE);
#endif
}
@@ -2150,7 +2146,7 @@ void GPU_state_init(void)
glCullFace(GL_BACK);
glDisable(GL_CULL_FACE);
- gpu_multisample(false);
+ gpu_disable_multisample();
}
void GPU_enable_program_point_size(void)
@@ -2385,7 +2381,7 @@ static GPUAttribStack state = {
};
#define AttribStack state
-#define Gwn_VertAttr state.attrib_stack[state.top]
+#define Attrib state.attrib_stack[state.top]
/**
* Replacement for glPush/PopAttributes
@@ -2395,48 +2391,48 @@ static GPUAttribStack state = {
*/
void gpuPushAttrib(eGPUAttribMask mask)
{
- Gwn_VertAttr.mask = mask;
+ Attrib.mask = mask;
if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) {
- Gwn_VertAttr.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
- glGetIntegerv(GL_DEPTH_FUNC, &Gwn_VertAttr.depth_func);
- glGetDoublev(GL_DEPTH_CLEAR_VALUE, &Gwn_VertAttr.depth_clear_value);
- glGetBooleanv(GL_DEPTH_WRITEMASK, (GLboolean *)&Gwn_VertAttr.depth_write_mask);
+ Attrib.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
+ glGetIntegerv(GL_DEPTH_FUNC, &Attrib.depth_func);
+ glGetDoublev(GL_DEPTH_CLEAR_VALUE, &Attrib.depth_clear_value);
+ glGetBooleanv(GL_DEPTH_WRITEMASK, (GLboolean *)&Attrib.depth_write_mask);
}
if ((mask & GPU_ENABLE_BIT) != 0) {
- Gwn_VertAttr.is_blend = glIsEnabled(GL_BLEND);
+ Attrib.is_blend = glIsEnabled(GL_BLEND);
for (int i = 0; i < 6; i++) {
- Gwn_VertAttr.is_clip_plane[i] = glIsEnabled(GL_CLIP_PLANE0 + i);
+ Attrib.is_clip_plane[i] = glIsEnabled(GL_CLIP_PLANE0 + i);
}
- Gwn_VertAttr.is_cull_face = glIsEnabled(GL_CULL_FACE);
- Gwn_VertAttr.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
- Gwn_VertAttr.is_dither = glIsEnabled(GL_DITHER);
- Gwn_VertAttr.is_line_smooth = glIsEnabled(GL_LINE_SMOOTH);
- Gwn_VertAttr.is_color_logic_op = glIsEnabled(GL_COLOR_LOGIC_OP);
- Gwn_VertAttr.is_multisample = glIsEnabled(GL_MULTISAMPLE);
- Gwn_VertAttr.is_polygon_offset_line = glIsEnabled(GL_POLYGON_OFFSET_LINE);
- Gwn_VertAttr.is_polygon_offset_fill = glIsEnabled(GL_POLYGON_OFFSET_FILL);
- Gwn_VertAttr.is_polygon_smooth = glIsEnabled(GL_POLYGON_SMOOTH);
- Gwn_VertAttr.is_sample_alpha_to_coverage = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE);
- Gwn_VertAttr.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
- Gwn_VertAttr.is_stencil_test = glIsEnabled(GL_STENCIL_TEST);
+ Attrib.is_cull_face = glIsEnabled(GL_CULL_FACE);
+ Attrib.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
+ Attrib.is_dither = glIsEnabled(GL_DITHER);
+ Attrib.is_line_smooth = glIsEnabled(GL_LINE_SMOOTH);
+ Attrib.is_color_logic_op = glIsEnabled(GL_COLOR_LOGIC_OP);
+ Attrib.is_multisample = glIsEnabled(GL_MULTISAMPLE);
+ Attrib.is_polygon_offset_line = glIsEnabled(GL_POLYGON_OFFSET_LINE);
+ Attrib.is_polygon_offset_fill = glIsEnabled(GL_POLYGON_OFFSET_FILL);
+ Attrib.is_polygon_smooth = glIsEnabled(GL_POLYGON_SMOOTH);
+ Attrib.is_sample_alpha_to_coverage = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE);
+ Attrib.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
+ Attrib.is_stencil_test = glIsEnabled(GL_STENCIL_TEST);
}
if ((mask & GPU_SCISSOR_BIT) != 0) {
- Gwn_VertAttr.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
- glGetIntegerv(GL_SCISSOR_BOX, (GLint *)&Gwn_VertAttr.scissor_box);
+ Attrib.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
+ glGetIntegerv(GL_SCISSOR_BOX, (GLint *)&Attrib.scissor_box);
}
if ((mask & GPU_VIEWPORT_BIT) != 0) {
- glGetDoublev(GL_DEPTH_RANGE, (GLdouble *)&Gwn_VertAttr.near_far);
- glGetIntegerv(GL_VIEWPORT, (GLint *)&Gwn_VertAttr.viewport);
+ glGetDoublev(GL_DEPTH_RANGE, (GLdouble *)&Attrib.near_far);
+ glGetIntegerv(GL_VIEWPORT, (GLint *)&Attrib.viewport);
}
if ((mask & GPU_BLEND_BIT) != 0) {
- Gwn_VertAttr.is_blend = glIsEnabled(GL_BLEND);
+ Attrib.is_blend = glIsEnabled(GL_BLEND);
}
BLI_assert(AttribStack.top < STATE_STACK_DEPTH);
@@ -2458,52 +2454,52 @@ void gpuPopAttrib(void)
BLI_assert(AttribStack.top > 0);
AttribStack.top--;
- GLint mask = Gwn_VertAttr.mask;
+ GLint mask = Attrib.mask;
if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) {
- restore_mask(GL_DEPTH_TEST, Gwn_VertAttr.is_depth_test);
- glDepthFunc(Gwn_VertAttr.depth_func);
- glClearDepth(Gwn_VertAttr.depth_clear_value);
- glDepthMask(Gwn_VertAttr.depth_write_mask);
+ restore_mask(GL_DEPTH_TEST, Attrib.is_depth_test);
+ glDepthFunc(Attrib.depth_func);
+ glClearDepth(Attrib.depth_clear_value);
+ glDepthMask(Attrib.depth_write_mask);
}
if ((mask & GPU_ENABLE_BIT) != 0) {
- restore_mask(GL_BLEND, Gwn_VertAttr.is_blend);
+ restore_mask(GL_BLEND, Attrib.is_blend);
for (int i = 0; i < 6; i++) {
- restore_mask(GL_CLIP_PLANE0 + i, Gwn_VertAttr.is_clip_plane[i]);
+ restore_mask(GL_CLIP_PLANE0 + i, Attrib.is_clip_plane[i]);
}
- restore_mask(GL_CULL_FACE, Gwn_VertAttr.is_cull_face);
- restore_mask(GL_DEPTH_TEST, Gwn_VertAttr.is_depth_test);
- restore_mask(GL_DITHER, Gwn_VertAttr.is_dither);
- restore_mask(GL_LINE_SMOOTH, Gwn_VertAttr.is_line_smooth);
- restore_mask(GL_COLOR_LOGIC_OP, Gwn_VertAttr.is_color_logic_op);
- restore_mask(GL_MULTISAMPLE, Gwn_VertAttr.is_multisample);
- restore_mask(GL_POLYGON_OFFSET_LINE, Gwn_VertAttr.is_polygon_offset_line);
- restore_mask(GL_POLYGON_OFFSET_FILL, Gwn_VertAttr.is_polygon_offset_fill);
- restore_mask(GL_POLYGON_SMOOTH, Gwn_VertAttr.is_polygon_smooth);
- restore_mask(GL_SAMPLE_ALPHA_TO_COVERAGE, Gwn_VertAttr.is_sample_alpha_to_coverage);
- restore_mask(GL_SCISSOR_TEST, Gwn_VertAttr.is_scissor_test);
- restore_mask(GL_STENCIL_TEST, Gwn_VertAttr.is_stencil_test);
+ restore_mask(GL_CULL_FACE, Attrib.is_cull_face);
+ restore_mask(GL_DEPTH_TEST, Attrib.is_depth_test);
+ restore_mask(GL_DITHER, Attrib.is_dither);
+ restore_mask(GL_LINE_SMOOTH, Attrib.is_line_smooth);
+ restore_mask(GL_COLOR_LOGIC_OP, Attrib.is_color_logic_op);
+ restore_mask(GL_MULTISAMPLE, Attrib.is_multisample);
+ restore_mask(GL_POLYGON_OFFSET_LINE, Attrib.is_polygon_offset_line);
+ restore_mask(GL_POLYGON_OFFSET_FILL, Attrib.is_polygon_offset_fill);
+ restore_mask(GL_POLYGON_SMOOTH, Attrib.is_polygon_smooth);
+ restore_mask(GL_SAMPLE_ALPHA_TO_COVERAGE, Attrib.is_sample_alpha_to_coverage);
+ restore_mask(GL_SCISSOR_TEST, Attrib.is_scissor_test);
+ restore_mask(GL_STENCIL_TEST, Attrib.is_stencil_test);
}
if ((mask & GPU_VIEWPORT_BIT) != 0) {
- glViewport(Gwn_VertAttr.viewport[0], Gwn_VertAttr.viewport[1], Gwn_VertAttr.viewport[2], Gwn_VertAttr.viewport[3]);
- glDepthRange(Gwn_VertAttr.near_far[0], Gwn_VertAttr.near_far[1]);
+ glViewport(Attrib.viewport[0], Attrib.viewport[1], Attrib.viewport[2], Attrib.viewport[3]);
+ glDepthRange(Attrib.near_far[0], Attrib.near_far[1]);
}
if ((mask & GPU_SCISSOR_BIT) != 0) {
- restore_mask(GL_SCISSOR_TEST, Gwn_VertAttr.is_scissor_test);
- glScissor(Gwn_VertAttr.scissor_box[0], Gwn_VertAttr.scissor_box[1], Gwn_VertAttr.scissor_box[2], Gwn_VertAttr.scissor_box[3]);
+ restore_mask(GL_SCISSOR_TEST, Attrib.is_scissor_test);
+ glScissor(Attrib.scissor_box[0], Attrib.scissor_box[1], Attrib.scissor_box[2], Attrib.scissor_box[3]);
}
if ((mask & GPU_BLEND_BIT) != 0) {
- restore_mask(GL_BLEND, Gwn_VertAttr.is_blend);
+ restore_mask(GL_BLEND, Attrib.is_blend);
}
}
-#undef Gwn_VertAttr
+#undef Attrib
#undef AttribStack
/** \} */
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 57df877bf18..73e86c1b391 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -149,7 +149,7 @@ void gpu_extensions_init(void)
else
GG.max_anisotropy = 1.0f;
- glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &GG.maxubobinds);
+ glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &GG.maxubobinds);
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GG.maxubosize);
#ifndef NDEBUG
@@ -178,14 +178,6 @@ void gpu_extensions_init(void)
GG.device = GPU_DEVICE_ATI;
GG.driver = GPU_DRIVER_OFFICIAL;
}
- /* XXX : TODO : Remove this once this sampling mipmap problem is gone.
- * https://github.com/dfelinto/opengl-sandbox/blob/downsample/README.md */
- else if (strstr(renderer, "AMD VEGA") &&
- strstr(vendor, "X.Org"))
- {
- GG.device = GPU_DEVICE_AMD_VEGA;
- GG.driver = GPU_DRIVER_OPENSOURCE;
- }
else if (strstr(vendor, "NVIDIA")) {
GG.device = GPU_DEVICE_NVIDIA;
GG.driver = GPU_DRIVER_OFFICIAL;
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index 09013cd29bd..8d8fb50d9b9 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -28,7 +28,9 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLI_math_base.h"
#include "BKE_global.h"
@@ -40,20 +42,91 @@
#include "GPU_shader.h"
#include "GPU_texture.h"
-static struct GPUFrameBufferGlobal {
- GLuint currentfb;
-} GG = {0};
+static ThreadLocal(GLuint) g_currentfb;
-/* Number of maximum output slots.
- * We support 5 outputs for now (usually we wouldn't need more to preserve fill rate) */
-#define GPU_FB_MAX_SLOTS 5
+typedef enum {
+ GPU_FB_DEPTH_ATTACHMENT = 0,
+ GPU_FB_DEPTH_STENCIL_ATTACHMENT,
+ GPU_FB_COLOR_ATTACHMENT0,
+ GPU_FB_COLOR_ATTACHMENT1,
+ GPU_FB_COLOR_ATTACHMENT2,
+ GPU_FB_COLOR_ATTACHMENT3,
+ GPU_FB_COLOR_ATTACHMENT4,
+ /* Number of maximum output slots.
+ * We support 5 outputs for now (usually we wouldn't need more to preserve fill rate). */
+ /* Keep in mind that GL max is GL_MAX_DRAW_BUFFERS and is at least 8, corresponding to
+ * the maximum number of COLOR attachments specified by glDrawBuffers. */
+ GPU_FB_MAX_ATTACHEMENT
+} GPUAttachmentType;
+
+#define GPU_FB_MAX_COLOR_ATTACHMENT (GPU_FB_MAX_ATTACHEMENT - GPU_FB_COLOR_ATTACHMENT0)
+
+#define GPU_FB_DIRTY_DRAWBUFFER (1 << 15)
+
+#define GPU_FB_ATTACHEMENT_IS_DIRTY(flag, type) ((flag & (1 << type)) != 0)
+#define GPU_FB_ATTACHEMENT_SET_DIRTY(flag, type) (flag |= (1 << type))
struct GPUFrameBuffer {
GLuint object;
- GPUTexture *colortex[GPU_FB_MAX_SLOTS];
- GPUTexture *depthtex;
+ GPUAttachment attachments[GPU_FB_MAX_ATTACHEMENT];
+ uint16_t dirty_flag;
+ int width, height;
+ bool multisample;
+ /* TODO Check that we always use the right context when binding
+ * (FBOs are not shared accross ogl contexts). */
+ // void *ctx;
};
+static GLenum convert_attachment_type_to_gl(GPUAttachmentType type)
+{
+ static const GLenum table[] = {
+ [GPU_FB_DEPTH_ATTACHMENT] = GL_DEPTH_ATTACHMENT,
+ [GPU_FB_DEPTH_STENCIL_ATTACHMENT] = GL_DEPTH_STENCIL_ATTACHMENT,
+ [GPU_FB_COLOR_ATTACHMENT0] = GL_COLOR_ATTACHMENT0,
+ [GPU_FB_COLOR_ATTACHMENT1] = GL_COLOR_ATTACHMENT1,
+ [GPU_FB_COLOR_ATTACHMENT2] = GL_COLOR_ATTACHMENT2,
+ [GPU_FB_COLOR_ATTACHMENT3] = GL_COLOR_ATTACHMENT3,
+ [GPU_FB_COLOR_ATTACHMENT4] = GL_COLOR_ATTACHMENT4
+ };
+ return table[type];
+}
+
+static GPUAttachmentType attachment_type_from_tex(GPUTexture *tex, int slot)
+{
+ switch (GPU_texture_format(tex)) {
+ case GPU_DEPTH_COMPONENT32F:
+ case GPU_DEPTH_COMPONENT24:
+ case GPU_DEPTH_COMPONENT16:
+ return GPU_FB_DEPTH_ATTACHMENT;
+ case GPU_DEPTH24_STENCIL8:
+ return GPU_FB_DEPTH_STENCIL_ATTACHMENT;
+ default:
+ return GPU_FB_COLOR_ATTACHMENT0 + slot;
+ }
+}
+
+static GLenum convert_buffer_bits_to_gl(GPUFrameBufferBits bits)
+{
+ GLbitfield mask = 0;
+ mask |= (bits & GPU_DEPTH_BIT) ? GL_DEPTH_BUFFER_BIT : 0;
+ mask |= (bits & GPU_STENCIL_BIT) ? GL_STENCIL_BUFFER_BIT : 0;
+ mask |= (bits & GPU_COLOR_BIT) ? GL_COLOR_BUFFER_BIT : 0;
+ return mask;
+}
+
+static GPUTexture *framebuffer_get_depth_tex(GPUFrameBuffer *fb)
+{
+ if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex)
+ return fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex;
+ else
+ return fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex;;
+}
+
+static GPUTexture *framebuffer_get_color_tex(GPUFrameBuffer *fb, int slot)
+{
+ return fb->attachments[GPU_FB_COLOR_ATTACHMENT0 + slot].tex;
+}
+
static void gpu_print_framebuffer_error(GLenum status, char err_out[256])
{
const char *format = "GPUFrameBuffer: framebuffer status %s\n";
@@ -94,296 +167,268 @@ static void gpu_print_framebuffer_error(GLenum status, char err_out[256])
GPUFrameBuffer *GPU_framebuffer_create(void)
{
- GPUFrameBuffer *fb;
+ /* We generate the FB object later at first use in order to
+ * create the framebuffer in the right opengl context. */
+ return MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");;
+}
- fb = MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
+static void gpu_framebuffer_init(GPUFrameBuffer *fb)
+{
glGenFramebuffers(1, &fb->object);
-
- if (!fb->object) {
- fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed.\n");
- GPU_framebuffer_free(fb);
- return NULL;
- }
-
- /* make sure no read buffer is enabled, so completeness check will not fail. We set those at binding time */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- glReadBuffer(GL_NONE);
- glDrawBuffer(GL_NONE);
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
- return fb;
}
-bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
+void GPU_framebuffer_free(GPUFrameBuffer *fb)
{
- GLenum attachment;
-
- if (slot >= GPU_FB_MAX_SLOTS) {
- fprintf(stderr,
- "Attaching to index %d framebuffer slot unsupported. "
- "Use at most %d\n", slot, GPU_FB_MAX_SLOTS);
- return false;
- }
-
- if ((G.debug & G_DEBUG)) {
- if (GPU_texture_bound_number(tex) != -1) {
- fprintf(stderr,
- "Feedback loop warning!: "
- "Attempting to attach texture to framebuffer while still bound to texture unit for drawing!\n");
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; type++) {
+ if (fb->attachments[type].tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, fb->attachments[type].tex);
}
}
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- GG.currentfb = fb->object;
-
- if (GPU_texture_stencil(tex) && GPU_texture_depth(tex))
- attachment = GL_DEPTH_STENCIL_ATTACHMENT;
- else if (GPU_texture_depth(tex))
- attachment = GL_DEPTH_ATTACHMENT;
- else
- attachment = GL_COLOR_ATTACHMENT0 + slot;
-
- glFramebufferTexture(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), mip);
+ /* This restores the framebuffer if it was bound */
+ glDeleteFramebuffers(1, &fb->object);
- if (GPU_texture_depth(tex))
- fb->depthtex = tex;
- else
- fb->colortex[slot] = tex;
-
- GPU_texture_framebuffer_set(tex, fb, slot);
+ if (g_currentfb == fb->object) {
+ g_currentfb = 0;
+ }
- return true;
+ MEM_freeN(fb);
}
-static bool gpu_framebuffer_texture_layer_attach_ex(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip, bool cubemap)
-{
- GLenum attachment;
- GLenum facetarget;
+/* ---------- Attach ----------- */
- if (slot >= GPU_FB_MAX_SLOTS) {
+static void gpu_framebuffer_texture_attach_ex(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
+{
+ if (slot >= GPU_FB_MAX_COLOR_ATTACHMENT) {
fprintf(stderr,
"Attaching to index %d framebuffer slot unsupported. "
- "Use at most %d\n", slot, GPU_FB_MAX_SLOTS);
- return false;
- }
-
- if ((G.debug & G_DEBUG)) {
- if (GPU_texture_bound_number(tex) != -1) {
- fprintf(stderr,
- "Feedback loop warning!: "
- "Attempting to attach texture to framebuffer while still bound to texture unit for drawing!\n");
- }
+ "Use at most %d\n", slot, GPU_FB_MAX_COLOR_ATTACHMENT);
+ return;
}
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- GG.currentfb = fb->object;
-
- if (GPU_texture_stencil(tex) && GPU_texture_depth(tex))
- attachment = GL_DEPTH_STENCIL_ATTACHMENT;
- else if (GPU_texture_depth(tex))
- attachment = GL_DEPTH_ATTACHMENT;
- else
- attachment = GL_COLOR_ATTACHMENT0 + slot;
+ GPUAttachmentType type = attachment_type_from_tex(tex, slot);
+ GPUAttachment *attachment = &fb->attachments[type];
- if (cubemap) {
- facetarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
- glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, facetarget, GPU_texture_opengl_bindcode(tex), mip);
+ if ((attachment->tex == tex) &&
+ (attachment->mip == mip) &&
+ (attachment->layer == layer))
+ {
+ return; /* Exact same texture already bound here. */
}
- else {
- glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), mip, layer);
+ else if (attachment->tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, attachment->tex);
}
- if (GPU_texture_depth(tex))
- fb->depthtex = tex;
- else
- fb->colortex[slot] = tex;
-
- GPU_texture_framebuffer_set(tex, fb, slot);
+ if (attachment->tex == NULL) {
+ GPU_texture_attach_framebuffer(tex, fb, type);
+ }
- return true;
+ attachment->tex = tex;
+ attachment->mip = mip;
+ attachment->layer = layer;
+ GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type);
}
-bool GPU_framebuffer_texture_layer_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
+void GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
{
- return gpu_framebuffer_texture_layer_attach_ex(fb, tex, slot, layer, mip, false);
+ gpu_framebuffer_texture_attach_ex(fb, tex, slot, -1, mip);
}
-bool GPU_framebuffer_texture_cubeface_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip)
+void GPU_framebuffer_texture_layer_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
{
- BLI_assert(GPU_texture_target(tex) == GL_TEXTURE_CUBE_MAP);
- return gpu_framebuffer_texture_layer_attach_ex(fb, tex, slot, face, mip, true);
+ /* NOTE: We could support 1D ARRAY texture. */
+ BLI_assert(GPU_texture_target(tex) == GL_TEXTURE_2D_ARRAY);
+ gpu_framebuffer_texture_attach_ex(fb, tex, slot, layer, mip);
}
-void GPU_framebuffer_texture_detach(GPUTexture *tex)
+void GPU_framebuffer_texture_cubeface_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip)
{
- GLenum attachment;
- GPUFrameBuffer *fb = GPU_texture_framebuffer(tex);
- int fb_attachment = GPU_texture_framebuffer_attachment(tex);
+ BLI_assert(GPU_texture_cube(tex));
+ gpu_framebuffer_texture_attach_ex(fb, tex, slot, face, mip);
+}
- if (!fb)
- return;
+/* ---------- Detach ----------- */
- if (GG.currentfb != fb->object) {
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- GG.currentfb = fb->object;
- }
+void GPU_framebuffer_texture_detach_slot(GPUFrameBuffer *fb, GPUTexture *tex, int type)
+{
+ GPUAttachment *attachment = &fb->attachments[type];
- if (GPU_texture_stencil(tex) && GPU_texture_depth(tex)) {
- fb->depthtex = NULL;
- attachment = GL_DEPTH_STENCIL_ATTACHMENT;
- }
- else if (GPU_texture_depth(tex)) {
- fb->depthtex = NULL;
- attachment = GL_DEPTH_ATTACHMENT;
- }
- else {
- BLI_assert(fb->colortex[fb_attachment] == tex);
- fb->colortex[fb_attachment] = NULL;
- attachment = GL_COLOR_ATTACHMENT0 + fb_attachment;
+ if (attachment->tex != tex) {
+ fprintf(stderr,
+ "Warning, attempting to detach Texture %p from framebuffer %p "
+ "but texture is not attached.\n", tex, fb);
+ return;
}
- glFramebufferTexture(GL_FRAMEBUFFER, attachment, 0, 0);
+ attachment->tex = NULL;
+ GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type);
+}
- GPU_texture_framebuffer_set(tex, NULL, -1);
+void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
+{
+ GPUAttachmentType type = GPU_texture_detach_framebuffer(tex, fb);
+ GPU_framebuffer_texture_detach_slot(fb, tex, type);
}
-void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
+/* ---------- Config (Attach & Detach) ----------- */
+
+/**
+ * First GPUAttachment in *config is always the depth/depth_stencil buffer.
+ * Following GPUAttachments are color buffers.
+ * Setting GPUAttachment.mip to -1 will leave the texture in this slot.
+ * Setting GPUAttachment.tex to NULL will detach the texture in this slot.
+ **/
+void GPU_framebuffer_config_array(GPUFrameBuffer *fb, const GPUAttachment *config, int config_ct)
{
- GPUFrameBuffer *fb = GPU_texture_framebuffer(tex);
- int fb_attachment = GPU_texture_framebuffer_attachment(tex);
+ if (config[0].tex) {
+ BLI_assert(GPU_texture_depth(config[0].tex));
+ gpu_framebuffer_texture_attach_ex(fb, config[0].tex, 0, config[0].layer, config[0].mip);
+ }
+ else if (config[0].mip == -1) {
+ /* Leave texture attached */
+ }
+ else if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex);
+ }
+ else if (fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex);
+ }
- if (!fb) {
- fprintf(stderr, "Error, texture not bound to framebuffer!\n");
- return;
+ int slot = 0;
+ for (int i = 1; i < config_ct; ++i, ++slot) {
+ if (config[i].tex != NULL) {
+ BLI_assert(GPU_texture_depth(config[i].tex) == false);
+ gpu_framebuffer_texture_attach_ex(fb, config[i].tex, slot, config[i].layer, config[i].mip);
+ }
+ else if (config[i].mip != -1) {
+ GPUTexture *tex = framebuffer_get_color_tex(fb, slot);
+ if (tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, tex);
+ }
+ }
}
+}
- /* push attributes */
- gpuPushAttrib(GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
- glDisable(GL_SCISSOR_TEST);
+/* ---------- Bind / Restore ----------- */
- /* bind framebuffer */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+static void gpu_framebuffer_attachment_attach(GPUAttachment *attach, GPUAttachmentType attach_type)
+{
+ int tex_bind = GPU_texture_opengl_bindcode(attach->tex);
+ GLenum gl_attachment = convert_attachment_type_to_gl(attach_type);
- if (GPU_texture_depth(tex)) {
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
+ if (attach->layer > -1) {
+ if (GPU_texture_cube(attach->tex)) {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, gl_attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X + attach->layer,
+ tex_bind, attach->mip);
+ }
+ else {
+ glFramebufferTextureLayer(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip, attach->layer);
+ }
}
else {
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffer(GL_COLOR_ATTACHMENT0 + fb_attachment);
- glReadBuffer(GL_COLOR_ATTACHMENT0 + fb_attachment);
- }
-
- if (GPU_texture_target(tex) == GL_TEXTURE_2D_MULTISAMPLE) {
- glEnable(GL_MULTISAMPLE);
+ glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip);
}
+}
- /* set default viewport */
- glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
- GG.currentfb = fb->object;
+static void gpu_framebuffer_attachment_detach(GPUAttachment *UNUSED(attachment), GPUAttachmentType attach_type)
+{
+ GLenum gl_attachment = convert_attachment_type_to_gl(attach_type);
+ glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, 0, 0);
}
-void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
+static void gpu_framebuffer_update_attachments(GPUFrameBuffer *fb)
{
- int numslots = 0, i;
- GLenum attachments[GPU_FB_MAX_SLOTS];
-
- if (!fb->colortex[slot]) {
- fprintf(stderr, "Error, framebuffer slot empty!\n");
- return;
- }
-
- for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
- if (fb->colortex[i]) {
- attachments[numslots] = GL_COLOR_ATTACHMENT0 + i;
+ GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT];
+ int numslots = 0;
+
+ BLI_assert(g_currentfb == fb->object);
+
+ /* Update attachments */
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
+
+ if (type >= GPU_FB_COLOR_ATTACHMENT0) {
+ if (fb->attachments[type].tex) {
+ gl_attachments[numslots] = convert_attachment_type_to_gl(type);
+ }
+ else {
+ gl_attachments[numslots] = GL_NONE;
+ }
numslots++;
}
- }
-
- /* push attributes */
- gpuPushAttrib(GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
- glDisable(GL_SCISSOR_TEST);
- /* bind framebuffer */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+ if (GPU_FB_ATTACHEMENT_IS_DIRTY(fb->dirty_flag, type) == false) {
+ continue;
+ }
+ else if (fb->attachments[type].tex != NULL) {
+ gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffers(numslots, attachments);
- glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
+ fb->multisample = (GPU_texture_samples(fb->attachments[type].tex) > 0);
+ fb->width = GPU_texture_width(fb->attachments[type].tex);
+ fb->height = GPU_texture_height(fb->attachments[type].tex);
+ }
+ else {
+ gpu_framebuffer_attachment_detach(&fb->attachments[type], type);
+ }
+ }
+ fb->dirty_flag = 0;
- /* set default viewport */
- glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
- GG.currentfb = fb->object;
+ /* Update draw buffers (color targets)
+ * This state is saved in the FBO */
+ if (numslots)
+ glDrawBuffers(numslots, gl_attachments);
+ else
+ glDrawBuffer(GL_NONE);
}
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
{
- int numslots = 0, i;
- GLenum attachments[GPU_FB_MAX_SLOTS];
- GLenum readattachement = 0;
- GPUTexture *tex;
+ if (fb->object == 0)
+ gpu_framebuffer_init(fb);
- for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
- if (fb->colortex[i]) {
- attachments[numslots] = GL_COLOR_ATTACHMENT0 + i;
- tex = fb->colortex[i];
+ if (g_currentfb != fb->object)
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- if (!readattachement)
- readattachement = GL_COLOR_ATTACHMENT0 + i;
+ g_currentfb = fb->object;
- numslots++;
- }
- }
-
- /* bind framebuffer */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+ if (fb->dirty_flag != 0)
+ gpu_framebuffer_update_attachments(fb);
- if (numslots == 0) {
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
- tex = fb->depthtex;
- }
- else {
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffers(numslots, attachments);
- glReadBuffer(readattachement);
+ /* TODO manually check for errors? */
+#if 0
+ char err_out[256];
+ if (!GPU_framebuffer_check_valid(fb, err_out)) {
+ printf("Invalid %s\n", err_out);
}
+#endif
- if (GPU_texture_target(tex) == GL_TEXTURE_2D_MULTISAMPLE) {
+ if (fb->multisample)
glEnable(GL_MULTISAMPLE);
- }
- glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
- GG.currentfb = fb->object;
+ glViewport(0, 0, fb->width, fb->height);
}
-void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
+void GPU_framebuffer_restore(void)
{
- /* Restore attributes. */
- gpuPopAttrib();
+ if (g_currentfb != 0) {
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ g_currentfb = 0;
+ }
}
-void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
+bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
{
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffer(GL_COLOR_ATTACHMENT0 + slot);
- glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
-
- /* push matrices and set default viewport and matrix */
- glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
- GG.currentfb = fb->object;
+ return (fb->object == g_currentfb) && (fb->object != 0);
}
-bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
+unsigned int GPU_framebuffer_current_get(void)
{
- return fb->object == GG.currentfb;
+ return g_currentfb;
}
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
{
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- GG.currentfb = fb->object;
+ if (!GPU_framebuffer_bound(fb))
+ GPU_framebuffer_bind(fb);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -396,172 +441,140 @@ bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
return true;
}
-void GPU_framebuffer_free(GPUFrameBuffer *fb)
-{
- int i;
- if (fb->depthtex)
- GPU_framebuffer_texture_detach(fb->depthtex);
-
- for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
- if (fb->colortex[i]) {
- GPU_framebuffer_texture_detach(fb->colortex[i]);
- }
- }
+/* ---------- Framebuffer Operations ----------- */
- if (fb->object) {
- glDeleteFramebuffers(1, &fb->object);
+#define CHECK_FRAMEBUFFER_IS_BOUND(_fb) \
+ BLI_assert(GPU_framebuffer_bound(_fb)); \
+ UNUSED_VARS_NDEBUG(_fb);
- if (GG.currentfb == fb->object) {
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- GG.currentfb = 0;
- }
- }
+/* Needs to be done after binding. */
+void GPU_framebuffer_viewport_set(GPUFrameBuffer *fb, int x, int y, int w, int h)
+{
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
- MEM_freeN(fb);
+ glViewport(x, y, w, h);
}
-void GPU_framebuffer_restore(void)
+void GPU_framebuffer_clear(
+ GPUFrameBuffer *fb, GPUFrameBufferBits buffers,
+ const float clear_col[4], float clear_depth, unsigned int clear_stencil)
{
- if (GG.currentfb != 0) {
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- GG.currentfb = 0;
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
+
+ if (buffers & GPU_COLOR_BIT) {
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glClearColor(clear_col[0], clear_col[1], clear_col[2], clear_col[3]);
+ }
+ if (buffers & GPU_DEPTH_BIT) {
+ glDepthMask(GL_TRUE);
+ glClearDepth(clear_depth);
}
+ if (buffers & GPU_STENCIL_BIT) {
+ glStencilMask(clear_stencil);
+ }
+
+ GLbitfield mask = convert_buffer_bits_to_gl(buffers);
+ glClear(mask);
}
-void GPU_framebuffer_blur(
- GPUFrameBuffer *fb, GPUTexture *tex,
- GPUFrameBuffer *blurfb, GPUTexture *blurtex)
+void GPU_framebuffer_read_depth(GPUFrameBuffer *fb, int x, int y, int w, int h, float *data)
{
- const float fullscreencos[4][2] = {{-1.0f, -1.0f}, {1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}};
- const float fullscreenuvs[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}};
-
- static Gwn_VertFormat format = {0};
- static Gwn_VertBuf vbo = {{0}};
- static Gwn_Batch batch = {{0}};
-
- const float scaleh[2] = {1.0f / GPU_texture_width(blurtex), 0.0f};
- const float scalev[2] = {0.0f, 1.0f / GPU_texture_height(tex)};
-
- GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
- if (!blur_shader)
- return;
-
- /* Preparing to draw quad */
- if (format.attrib_ct == 0) {
- unsigned int i = 0;
- /* Vertex format */
- unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned int uvs = GWN_vertformat_attr_add(&format, "uvs", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
-
- /* Vertices */
- GWN_vertbuf_init_with_format(&vbo, &format);
- GWN_vertbuf_data_alloc(&vbo, 36);
-
- for (int j = 0; j < 3; ++j) {
- GWN_vertbuf_attr_set(&vbo, uvs, i, fullscreenuvs[j]);
- GWN_vertbuf_attr_set(&vbo, pos, i++, fullscreencos[j]);
- }
- for (int j = 1; j < 4; ++j) {
- GWN_vertbuf_attr_set(&vbo, uvs, i, fullscreenuvs[j]);
- GWN_vertbuf_attr_set(&vbo, pos, i++, fullscreencos[j]);
- }
+ GLenum type = GL_DEPTH_COMPONENT;
+ glReadBuffer(GL_COLOR_ATTACHMENT0); /* This is OK! */
+ glReadPixels(x, y, w, h, type, GL_FLOAT, data);
+}
- GWN_batch_init(&batch, GL_TRIANGLES, &vbo, NULL);
+void GPU_framebuffer_read_color(
+ GPUFrameBuffer *fb, int x, int y, int w, int h, int channels, int slot, float *data)
+{
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
+
+ GLenum type;
+ switch (channels) {
+ case 1: type = GL_RED; break;
+ case 2: type = GL_RG; break;
+ case 3: type = GL_RGB; break;
+ case 4: type = GL_RGBA; break;
+ default:
+ BLI_assert(false && "wrong number of read channels");
+ return;
}
-
- glDisable(GL_DEPTH_TEST);
-
- /* Blurring horizontally */
- /* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
- * pushing unnecessary matrices onto the OpenGL stack. */
- glBindFramebuffer(GL_FRAMEBUFFER, blurfb->object);
- glDrawBuffer(GL_COLOR_ATTACHMENT0);
-
- /* avoid warnings from texture binding */
- GG.currentfb = blurfb->object;
-
- glViewport(0, 0, GPU_texture_width(blurtex), GPU_texture_height(blurtex));
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
+ glReadPixels(x, y, w, h, type, GL_FLOAT, data);
+}
- GPU_texture_bind(tex, 0);
+/* read_slot and write_slot are only used for color buffers. */
+void GPU_framebuffer_blit(
+ GPUFrameBuffer *fb_read, int read_slot,
+ GPUFrameBuffer *fb_write, int write_slot,
+ GPUFrameBufferBits blit_buffers)
+{
+ BLI_assert(blit_buffers != 0);
- GWN_batch_program_set_builtin(&batch, GPU_SHADER_SEP_GAUSSIAN_BLUR);
- GWN_batch_uniform_2f(&batch, "ScaleU", scaleh[0], scaleh[1]);
- GWN_batch_uniform_1i(&batch, "textureSource", GL_TEXTURE0);
- GWN_batch_draw(&batch);
+ GLuint prev_fb = g_currentfb;
- /* Blurring vertically */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- glDrawBuffer(GL_COLOR_ATTACHMENT0);
-
- GG.currentfb = fb->object;
-
- glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
+ /* Framebuffers must be up to date. This simplify this function. */
+ if (fb_read->dirty_flag != 0 || fb_read->object == 0) {
+ GPU_framebuffer_bind(fb_read);
+ }
+ if (fb_write->dirty_flag != 0 || fb_write->object == 0) {
+ GPU_framebuffer_bind(fb_write);
+ }
- GPU_texture_bind(blurtex, 0);
+ const bool do_color = (blit_buffers & GPU_COLOR_BIT);
+ const bool do_depth = (blit_buffers & GPU_DEPTH_BIT);
+ const bool do_stencil = (blit_buffers & GPU_STENCIL_BIT);
- /* Hack to make the following uniform stick */
- GWN_batch_program_set_builtin(&batch, GPU_SHADER_SEP_GAUSSIAN_BLUR);
- GWN_batch_uniform_2f(&batch, "ScaleU", scalev[0], scalev[1]);
- GWN_batch_uniform_1i(&batch, "textureSource", GL_TEXTURE0);
- GWN_batch_draw(&batch);
-}
+ GPUTexture *read_tex = (do_depth || do_stencil)
+ ? framebuffer_get_depth_tex(fb_read)
+ : framebuffer_get_color_tex(fb_read, read_slot);
+ GPUTexture *write_tex = (do_depth || do_stencil)
+ ? framebuffer_get_depth_tex(fb_write)
+ : framebuffer_get_color_tex(fb_write, read_slot);
-void GPU_framebuffer_blit(
- GPUFrameBuffer *fb_read, int read_slot, GPUFrameBuffer *fb_write,
- int write_slot, bool use_depth, bool use_stencil)
-{
- GPUTexture *read_tex = (use_depth || use_stencil) ? fb_read->depthtex : fb_read->colortex[read_slot];
- GPUTexture *write_tex = (use_depth || use_stencil) ? fb_write->depthtex : fb_write->colortex[write_slot];
- int read_attach = (use_depth) ? GL_DEPTH_ATTACHMENT :
- (use_stencil) ? GL_DEPTH_STENCIL_ATTACHMENT :
- GL_COLOR_ATTACHMENT0 + GPU_texture_framebuffer_attachment(read_tex);
- int write_attach = (use_depth) ? GL_DEPTH_ATTACHMENT :
- (use_stencil) ? GL_DEPTH_STENCIL_ATTACHMENT :
- GL_COLOR_ATTACHMENT0 + GPU_texture_framebuffer_attachment(write_tex);
- int read_bind = GPU_texture_opengl_bindcode(read_tex);
- int write_bind = GPU_texture_opengl_bindcode(write_tex);
- const int read_w = GPU_texture_width(read_tex);
- const int read_h = GPU_texture_height(read_tex);
- const int write_w = GPU_texture_width(write_tex);
- const int write_h = GPU_texture_height(write_tex);
-
-
- /* Never both! */
- BLI_assert(!(use_depth && use_stencil));
-
- if (use_depth) {
+ if (do_depth) {
BLI_assert(GPU_texture_depth(read_tex) && GPU_texture_depth(write_tex));
BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex));
}
- else if (use_stencil) {
+ if (do_stencil) {
BLI_assert(GPU_texture_stencil(read_tex) && GPU_texture_stencil(write_tex));
BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex));
}
+ if (GPU_texture_samples(write_tex) != 0 ||
+ GPU_texture_samples(read_tex) != 0)
+ {
+ /* Can only blit multisample textures to another texture of the same size. */
+ BLI_assert((fb_read->width == fb_write->width) &&
+ (fb_read->height == fb_write->height));
+ }
- /* read from multi-sample buffer */
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb_read->object);
- glFramebufferTexture2D(
- GL_READ_FRAMEBUFFER, read_attach,
- GPU_texture_target(read_tex), read_bind, 0);
- BLI_assert(glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
-
- /* write into new single-sample buffer */
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_write->object);
- glFramebufferTexture2D(
- GL_DRAW_FRAMEBUFFER, write_attach,
- GPU_texture_target(write_tex), write_bind, 0);
- BLI_assert(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
- glDrawBuffer((use_depth || use_stencil) ? GL_COLOR_ATTACHMENT0 : read_attach);
- glBlitFramebuffer(0, 0, read_w, read_h, 0, 0, write_w, write_h,
- (use_depth) ? GL_DEPTH_BUFFER_BIT :
- (use_stencil) ? GL_STENCIL_BUFFER_BIT :
- GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ if (do_color) {
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + read_slot);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0 + write_slot);
+ /* XXX we messed with the glDrawBuffer, this will reset the
+ * glDrawBuffers the next time we bind fb_write. */
+ fb_write->dirty_flag = GPU_FB_DIRTY_DRAWBUFFER;
+ }
+
+ GLbitfield mask = convert_buffer_bits_to_gl(blit_buffers);
+
+ glBlitFramebuffer(0, 0, fb_read->width, fb_read->height,
+ 0, 0, fb_write->width, fb_write->height,
+ mask, GL_NEAREST);
/* Restore previous framebuffer */
- glBindFramebuffer(GL_FRAMEBUFFER, GG.currentfb);
- glDrawBuffer(GL_COLOR_ATTACHMENT0);
+ if (fb_write->object == prev_fb) {
+ GPU_framebuffer_bind(fb_write); /* To update drawbuffers */
+ }
+ else {
+ glBindFramebuffer(GL_FRAMEBUFFER, prev_fb);
+ g_currentfb = prev_fb;
+ }
}
/**
@@ -569,77 +582,65 @@ void GPU_framebuffer_blit(
* This function only takes care of the correct texture handling. It execute the callback for each texture level.
**/
void GPU_framebuffer_recursive_downsample(
- GPUFrameBuffer *fb, GPUTexture *tex, int num_iter, void (*callback)(void *userData, int level), void *userData)
+ GPUFrameBuffer *fb, int max_lvl,
+ void (*callback)(void *userData, int level), void *userData)
{
- int i;
- int current_dim[2] = {GPU_texture_width(tex), GPU_texture_height(tex)};
- GLenum attachment;
-
- /* Manually setup framebuffer to not use GPU_texture_framebuffer_set() */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- GG.currentfb = fb->object;
-
- if (GPU_texture_stencil(tex) && GPU_texture_depth(tex))
- attachment = GL_DEPTH_STENCIL_ATTACHMENT;
- else if (GPU_texture_depth(tex))
- attachment = GL_DEPTH_ATTACHMENT;
- else
- attachment = GL_COLOR_ATTACHMENT0;
-
- /* last bound prevails here, better allow explicit control here too */
- if (GPU_texture_depth(tex)) {
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
- }
- else {
- glDrawBuffer(GL_COLOR_ATTACHMENT0);
- glReadBuffer(GL_COLOR_ATTACHMENT0);
+ /* Framebuffer must be up to date and bound. This simplify this function. */
+ if (g_currentfb != fb->object || fb->dirty_flag != 0 || fb->object == 0) {
+ GPU_framebuffer_bind(fb);
}
+ /* HACK: We make the framebuffer appear not bound in order to
+ * not trigger any error in GPU_texture_bind(). */
+ GLuint prev_fb = g_currentfb;
+ g_currentfb = 0;
- for (i = 1; i < num_iter + 1; i++) {
-
+ int i;
+ int current_dim[2] = {fb->width, fb->height};
+ for (i = 1; i < max_lvl + 1; i++) {
/* calculate next viewport size */
- current_dim[0] /= 2;
- current_dim[1] /= 2;
-
- if (GPU_type_matches(GPU_DEVICE_AMD_VEGA, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) {
- /* NOTE : here 16 is because of a bug on AMD Vega GPU + non-pro drivers, that prevents us
- * from sampling mipmaps that are smaller or equal to 16px. (9) */
- if (current_dim[0] <= 16 && current_dim[1] <= 16) {
- break;
- }
- }
- else {
- if (current_dim[0] <= 2 && current_dim[1] <= 2) {
- /* Cannot reduce further. */
- break;
+ current_dim[0] = max_ii(current_dim[0] / 2, 1);
+ current_dim[1] = max_ii(current_dim[1] / 2, 1);
+
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
+ if (fb->attachments[type].tex != NULL) {
+ /* bind next level for rendering but first restrict fetches only to previous level */
+ GPUTexture *tex = fb->attachments[type].tex;
+ GPU_texture_bind(tex, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, i - 1);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
+ GPU_texture_unbind(tex);
+ /* copy attachment and replace miplevel. */
+ GPUAttachment attachment = fb->attachments[type];
+ attachment.mip = i;
+ gpu_framebuffer_attachment_attach(&attachment, type);
}
}
- /* ensure that the viewport size is always at least 1x1 */
- CLAMP_MIN(current_dim[0], 1);
- CLAMP_MIN(current_dim[1], 1);
+ BLI_assert(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER));
glViewport(0, 0, current_dim[0], current_dim[1]);
-
- /* bind next level for rendering but first restrict fetches only to previous level */
- GPU_texture_bind(tex, 0);
- glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, i - 1);
- glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
- GPU_texture_unbind(tex);
-
- glFramebufferTexture(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), i);
-
callback(userData, i);
- }
- glFramebufferTexture(GL_FRAMEBUFFER, attachment, 0, 0);
+ if (current_dim[0] == 1 && current_dim[1] == 1)
+ break;
+ }
+
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
+ if (fb->attachments[type].tex != NULL) {
+ /* reset mipmap level range */
+ GPUTexture *tex = fb->attachments[type].tex;
+ GPU_texture_bind(tex, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
+ GPU_texture_unbind(tex);
+ /* Reattach original level */
+ /* NOTE: This is not necessary but this makes the FBO config
+ * remain in sync with the GPUFrameBuffer config. */
+ gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
+ }
+ }
- /* reset mipmap level range for the depth image */
- GPU_texture_bind(tex, 0);
- glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
- GPU_texture_unbind(tex);
+ g_currentfb = prev_fb;
}
/* GPUOffScreen */
@@ -650,55 +651,29 @@ struct GPUOffScreen {
GPUTexture *depth;
};
-GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, bool high_bitdepth, char err_out[256])
+GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, bool depth, bool high_bitdepth, char err_out[256])
{
GPUOffScreen *ofs;
ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
- ofs->fb = GPU_framebuffer_create();
- if (!ofs->fb) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
-
- if (samples) {
- if (!GLEW_ARB_texture_multisample ||
- /* This is required when blitting from a multi-sampled buffers,
- * even though we're not scaling. */
- !GLEW_EXT_framebuffer_multisample_blit_scaled)
- {
- samples = 0;
- }
- }
-
- ofs->depth = GPU_texture_create_depth_with_stencil_multisample(width, height, samples, err_out);
- if (!ofs->depth) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
-
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, 0)) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
+ ofs->color = GPU_texture_create_2D_custom_multisample(width, height, 4,
+ (high_bitdepth) ? GPU_RGBA16F : GPU_RGBA8, NULL, samples, err_out);
- if (high_bitdepth) {
- ofs->color = GPU_texture_create_2D_custom_multisample(width, height, 4, GPU_RGBA16F, NULL, samples, err_out);
- }
- else {
- ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, samples, err_out);
- }
- if (!ofs->color) {
- GPU_offscreen_free(ofs);
- return NULL;
+ if (depth) {
+ ofs->depth = GPU_texture_create_depth_with_stencil_multisample(width, height, samples, err_out);
}
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, 0)) {
+ if (!ofs->depth || !ofs->color) {
GPU_offscreen_free(ofs);
return NULL;
}
+ GPU_framebuffer_ensure_config(&ofs->fb, {
+ GPU_ATTACHMENT_TEXTURE(ofs->depth),
+ GPU_ATTACHMENT_TEXTURE(ofs->color)
+ });
+
/* check validity at the very end! */
if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
GPU_offscreen_free(ofs);
@@ -724,20 +699,19 @@ void GPU_offscreen_free(GPUOffScreen *ofs)
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
{
- glDisable(GL_SCISSOR_TEST);
- if (save)
- GPU_texture_bind_as_framebuffer(ofs->color);
- else {
- GPU_framebuffer_bind_no_save(ofs->fb, 0);
+ if (save) {
+ gpuPushAttrib(GPU_SCISSOR_BIT | GPU_VIEWPORT_BIT);
}
+ glDisable(GL_SCISSOR_TEST);
+ GPU_framebuffer_bind(ofs->fb);
}
-void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
+void GPU_offscreen_unbind(GPUOffScreen *UNUSED(ofs), bool restore)
{
- if (restore)
- GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
GPU_framebuffer_restore();
- glEnable(GL_SCISSOR_TEST);
+ if (restore) {
+ gpuPopAttrib();
+ }
}
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
@@ -745,46 +719,28 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
const int w = GPU_texture_width(ofs->color);
const int h = GPU_texture_height(ofs->color);
+ BLI_assert(type == GL_UNSIGNED_BYTE || type == GL_FLOAT);
+
if (GPU_texture_target(ofs->color) == GL_TEXTURE_2D_MULTISAMPLE) {
/* For a multi-sample texture,
* we need to create an intermediate buffer to blit to,
* before its copied using 'glReadPixels' */
-
- /* not needed since 'ofs' needs to be bound to the framebuffer already */
-// #define USE_FBO_CTX_SWITCH
-
GLuint fbo_blit = 0;
GLuint tex_blit = 0;
- GLenum status;
/* create texture for new 'fbo_blit' */
glGenTextures(1, &tex_blit);
- if (!tex_blit) {
- goto finally;
- }
-
glBindTexture(GL_TEXTURE_2D, tex_blit);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, type, 0);
-
-#ifdef USE_FBO_CTX_SWITCH
- /* read from multi-sample buffer */
- glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs->color->fb->object);
- glFramebufferTexture2D(
- GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + ofs->color->fb_attachment,
- GL_TEXTURE_2D_MULTISAMPLE, ofs->color->bindcode, 0);
- status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- goto finally;
- }
-#endif
+ glTexImage2D(GL_TEXTURE_2D, 0, (type == GL_FLOAT) ? GL_RGBA16F : GL_RGBA8,
+ w, h, 0, GL_RGBA, type, 0);
/* write into new single-sample buffer */
glGenFramebuffers(1, &fbo_blit);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit);
- glFramebufferTexture2D(
- GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, tex_blit, 0);
- status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, tex_blit, 0);
+
+ GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
goto finally;
}
@@ -796,21 +752,13 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_blit);
glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
-#ifdef USE_FBO_CTX_SWITCH
/* restore the original frame-bufer */
- glBindFramebuffer(GL_FRAMEBUFFER, ofs->color->fb->object);
-#undef USE_FBO_CTX_SWITCH
-#endif
-
+ glBindFramebuffer(GL_FRAMEBUFFER, ofs->fb->object);
finally:
/* cleanup */
- if (tex_blit) {
- glDeleteTextures(1, &tex_blit);
- }
- if (fbo_blit) {
- glDeleteFramebuffers(1, &fbo_blit);
- }
+ glDeleteTextures(1, &tex_blit);
+ glDeleteFramebuffers(1, &fbo_blit);
}
else {
glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
@@ -827,9 +775,9 @@ int GPU_offscreen_height(const GPUOffScreen *ofs)
return GPU_texture_height(ofs->color);
}
-int GPU_offscreen_color_texture(const GPUOffScreen *ofs)
+GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *ofs)
{
- return GPU_texture_opengl_bindcode(ofs->color);
+ return ofs->color;
}
/* only to be used by viewport code! */
diff --git a/source/blender/gpu/intern/gpu_lamp.c b/source/blender/gpu/intern/gpu_lamp.c
index 3c49c057b49..8968521060d 100644
--- a/source/blender/gpu/intern/gpu_lamp.c
+++ b/source/blender/gpu/intern/gpu_lamp.c
@@ -49,6 +49,7 @@
#include "GPU_material.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
+#include "GPU_batch.h"
#include "gpu_lamp_private.h"
@@ -266,90 +267,35 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) ||
(la->type == LA_SUN && (la->mode & LA_SHAD_RAY)))
{
- /* opengl */
- lamp->fb = GPU_framebuffer_create();
- if (!lamp->fb) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
- /* Shadow depth map */
lamp->depthtex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
- if (!lamp->depthtex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- GPU_texture_bind(lamp->depthtex, 0);
- GPU_texture_compare_mode(lamp->depthtex, true);
- GPU_texture_unbind(lamp->depthtex);
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* Shadow color map */
lamp->tex = gpu_lamp_create_vsm_shadow_map(lamp->size);
- if (!lamp->tex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* FBO and texture for blurring */
- lamp->blurfb = GPU_framebuffer_create();
- if (!lamp->blurfb) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
lamp->blurtex = gpu_lamp_create_vsm_shadow_map(lamp->size * 0.5);
- if (!lamp->blurtex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
- if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
+ lamp->fb = GPU_framebuffer_create();
+ GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, 0);
+ GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, 0);
- /* we need to properly bind to test for completeness */
- GPU_texture_bind_as_framebuffer(lamp->blurtex);
+ lamp->blurfb = GPU_framebuffer_create();
+ GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, 0);
- if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) {
+ if (!GPU_framebuffer_check_valid(lamp->fb, NULL) ||
+ !GPU_framebuffer_check_valid(lamp->blurfb, NULL))
+ {
gpu_lamp_shadow_free(lamp);
return lamp;
}
-
- GPU_framebuffer_texture_unbind(lamp->blurfb, lamp->blurtex);
}
else {
lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
- if (!lamp->tex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
GPU_texture_bind(lamp->tex, 0);
GPU_texture_compare_mode(lamp->tex, true);
+ GPU_texture_filter_mode(lamp->tex, true);
GPU_texture_unbind(lamp->tex);
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
+ lamp->fb = GPU_framebuffer_create();
+ GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, 0);
if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
gpu_lamp_shadow_free(lamp);
@@ -437,7 +383,7 @@ void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsiz
/* opengl */
glDisable(GL_SCISSOR_TEST);
- GPU_texture_bind_as_framebuffer(lamp->tex);
+ GPU_framebuffer_bind(lamp->fb);
if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE)
GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE));
@@ -447,14 +393,45 @@ void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsiz
*winsize = lamp->size;
}
+static void gpu_lamp_shadow_blur(GPULamp *lamp)
+{
+ const float scaleh[2] = {1.0f / GPU_texture_width(lamp->blurtex), 0.0f};
+ const float scalev[2] = {0.0f, 1.0f / GPU_texture_height(lamp->tex)};
+
+ GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
+
+ if (!blur_shader)
+ return;
+
+ int tex_loc = GPU_shader_get_uniform(blur_shader, "textureSource");
+ int scale_loc = GPU_shader_get_uniform(blur_shader, "ScaleU");
+
+ glDisable(GL_DEPTH_TEST);
+
+ GPU_shader_bind(blur_shader);
+
+ /* Blurring horizontally */
+ GPU_framebuffer_bind(lamp->blurfb);
+ GPU_texture_bind(lamp->tex, 0);
+ GPU_shader_uniform_vector(blur_shader, scale_loc, 2, 1, scaleh);
+ GPU_shader_uniform_texture(blur_shader, tex_loc, lamp->tex);
+ GWN_draw_primitive(GL_TRIANGLES, 3);
+
+ /* Blurring vertically */
+ GPU_framebuffer_bind(lamp->fb);
+ GPU_texture_bind(lamp->blurtex, 0);
+ GPU_shader_uniform_vector(blur_shader, scale_loc, 2, 1, scalev);
+ GPU_shader_uniform_texture(blur_shader, tex_loc, lamp->blurtex);
+ GWN_draw_primitive(GL_TRIANGLES, 3);
+}
+
void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
{
if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
GPU_shader_unbind();
- GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex);
+ gpu_lamp_shadow_blur(lamp);
}
- GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex);
GPU_framebuffer_restore();
glEnable(GL_SCISSOR_TEST);
}
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 2e6c1cbf9df..a408a41513a 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -68,6 +68,8 @@
#include "GPU_texture.h"
#include "GPU_uniformbuffer.h"
+#include "DRW_engine.h"
+
#include "gpu_codegen.h"
#include "gpu_lamp_private.h"
@@ -103,6 +105,7 @@ struct GPUMaterial {
/* material for mesh surface, worlds or something else.
* some code generation is done differently depending on the use case */
int type; /* DEPRECATED */
+ GPUMaterialStatus status;
const void *engine_type; /* attached engine type */
int options; /* to identify shader variations (shadow, probe, world background...) */
@@ -113,6 +116,7 @@ struct GPUMaterial {
/* for binding the material */
GPUPass *pass;
+ ListBase inputs; /* GPUInput */
GPUVertexAttribs attribs;
int builtins;
int alpha, obcolalpha;
@@ -142,7 +146,10 @@ struct GPUMaterial {
*/
int domain;
+ /* Used by 2.8 pipeline */
GPUUniformBuffer *ubo; /* UBOs for shader uniforms. */
+
+ /* Eevee SSS */
GPUUniformBuffer *sss_profile; /* UBO containing SSS profile. */
GPUTexture *sss_tex_profile; /* Texture containing SSS profile. */
float *sss_radii; /* UBO containing SSS profile. */
@@ -215,12 +222,14 @@ static int gpu_material_construct_end(GPUMaterial *material, const char *passnam
{
if (material->outlink) {
GPUNodeLink *outlink = material->outlink;
- material->pass = GPU_generate_pass(&material->nodes, outlink,
+ material->pass = GPU_generate_pass(&material->nodes, &material->inputs, outlink,
&material->attribs, &material->builtins, material->type,
passname,
material->is_opensubdiv,
GPU_material_use_new_shading_nodes(material));
+ material->status = (material->pass) ? GPU_MAT_SUCCESS : GPU_MAT_FAILED;
+
if (!material->pass)
return 0;
@@ -270,8 +279,14 @@ void GPU_material_free(ListBase *gpumaterial)
for (LinkData *link = gpumaterial->first; link; link = link->next) {
GPUMaterial *material = link->data;
+ /* Cancel / wait any pending lazy compilation. */
+ DRW_deferred_shader_remove(material);
+
+ GPU_pass_free_nodes(&material->nodes);
+ GPU_inputs_free(&material->inputs);
+
if (material->pass)
- GPU_pass_free(material->pass);
+ GPU_pass_release(material->pass);
if (material->ubo != NULL) {
GPU_uniformbuffer_free(material->ubo);
@@ -343,7 +358,7 @@ void GPU_material_bind(
}
/* note material must be bound before setting uniforms */
- GPU_pass_bind(material->pass, time, mipmap);
+ GPU_pass_bind(material->pass, &material->inputs, time, mipmap);
/* handle per material built-ins */
if (material->builtins & GPU_VIEW_MATRIX) {
@@ -363,7 +378,7 @@ void GPU_material_bind(
}
}
- GPU_pass_update_uniforms(material->pass);
+ GPU_pass_update_uniforms(material->pass, &material->inputs);
material->bound = 1;
}
@@ -417,7 +432,7 @@ void GPU_material_bind_uniforms(
GPU_shader_uniform_vector(shader, material->partscalarpropsloc, 4, 1, pi->scalprops);
}
if (material->builtins & GPU_PARTICLE_LOCATION) {
- GPU_shader_uniform_vector(shader, material->partcoloc, 3, 1, pi->location);
+ GPU_shader_uniform_vector(shader, material->partcoloc, 4, 1, pi->location);
}
if (material->builtins & GPU_PARTICLE_VELOCITY) {
GPU_shader_uniform_vector(shader, material->partvel, 3, 1, pi->velocity);
@@ -436,7 +451,7 @@ void GPU_material_unbind(GPUMaterial *material)
{
if (material->pass) {
material->bound = 0;
- GPU_pass_unbind(material->pass);
+ GPU_pass_unbind(material->pass, &material->inputs);
}
}
@@ -460,6 +475,11 @@ GPUPass *GPU_material_get_pass(GPUMaterial *material)
return material->pass;
}
+ListBase *GPU_material_get_inputs(GPUMaterial *material)
+{
+ return &material->inputs;
+}
+
GPUUniformBuffer *GPU_material_get_uniform_buffer(GPUMaterial *material)
{
return material->ubo;
@@ -557,7 +577,9 @@ static float eval_profile(float r, short falloff_type, float sharpness, float pa
{
r = fabsf(r);
- if (falloff_type == SHD_SUBSURFACE_BURLEY) {
+ if (falloff_type == SHD_SUBSURFACE_BURLEY ||
+ falloff_type == SHD_SUBSURFACE_RANDOM_WALK)
+ {
return burley_profile(r, param) / BURLEY_TRUNCATE_CDF;
}
else if (falloff_type == SHD_SUBSURFACE_CUBIC) {
@@ -598,7 +620,9 @@ static void compute_sss_kernel(
/* Christensen-Burley fitting */
float l[3], d[3];
- if (falloff_type == SHD_SUBSURFACE_BURLEY) {
+ if (falloff_type == SHD_SUBSURFACE_BURLEY ||
+ falloff_type == SHD_SUBSURFACE_RANDOM_WALK)
+ {
mul_v3_v3fl(l, rad, 0.25f * M_1_PI);
const float A = 1.0f;
const float s = 1.9f - A + 3.5f * (A - 0.8f) * (A - 0.8f);
@@ -825,6 +849,12 @@ void gpu_material_add_node(GPUMaterial *material, GPUNode *node)
BLI_addtail(&material->nodes, node);
}
+/* Return true if the material compilation has not yet begin or begin. */
+GPUMaterialStatus GPU_material_status(GPUMaterial *mat)
+{
+ return mat->status;
+}
+
/* Code generation */
bool GPU_material_do_color_management(GPUMaterial *mat)
@@ -2486,10 +2516,8 @@ GPUMaterial *GPU_material_from_nodetree_find(
*/
GPUMaterial *GPU_material_from_nodetree(
Scene *scene, struct bNodeTree *ntree, ListBase *gpumaterials, const void *engine_type, int options,
- const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines)
+ const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines, bool deferred)
{
- GPUMaterial *mat;
- GPUNodeLink *outlink;
LinkData *link;
bool has_volume_output, has_surface_output;
@@ -2497,7 +2525,7 @@ GPUMaterial *GPU_material_from_nodetree(
BLI_assert(GPU_material_from_nodetree_find(gpumaterials, engine_type, options) == NULL);
/* allocate material */
- mat = GPU_material_construct_begin(NULL); /* TODO remove GPU_material_construct_begin */
+ GPUMaterial *mat = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial");;
mat->scene = scene;
mat->engine_type = engine_type;
mat->options = options;
@@ -2512,11 +2540,15 @@ GPUMaterial *GPU_material_from_nodetree(
mat->domain |= GPU_DOMAIN_VOLUME;
}
- /* Let Draw manager finish the construction. */
- if (mat->outlink) {
- outlink = mat->outlink;
- mat->pass = GPU_generate_pass_new(
- mat, &mat->nodes, outlink, &mat->attribs, vert_code, geom_code, frag_lib, defines);
+ if (!deferred) {
+ GPU_material_generate_pass(mat, vert_code, geom_code, frag_lib, defines);
+ }
+ else if (mat->outlink) {
+ /* Prune the unused nodes and extract attribs before compiling so the
+ * generated VBOs are ready to accept the future shader. */
+ GPU_nodes_prune(&mat->nodes, mat->outlink);
+ GPU_nodes_get_vertex_attributes(&mat->nodes, &mat->attribs);
+ mat->status = GPU_MAT_QUEUED;
}
/* note that even if building the shader fails in some way, we still keep
@@ -2530,6 +2562,21 @@ GPUMaterial *GPU_material_from_nodetree(
return mat;
}
+/* Calls this function if /a mat was created with deferred compilation. */
+void GPU_material_generate_pass(
+ GPUMaterial *mat, const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines)
+{
+ BLI_assert(mat->pass == NULL); /* Only run once! */
+ if (mat->outlink) {
+ mat->pass = GPU_generate_pass_new(
+ mat, mat->outlink, &mat->attribs, &mat->nodes, &mat->inputs, vert_code, geom_code, frag_lib, defines);
+ mat->status = (mat->pass) ? GPU_MAT_SUCCESS : GPU_MAT_FAILED;
+ }
+ else {
+ mat->status = GPU_MAT_FAILED;
+ }
+}
+
GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_opensubdiv)
{
GPUMaterial *mat;
@@ -2692,7 +2739,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
if (pass && pass->fragmentcode && pass->vertexcode) {
shader = MEM_callocN(sizeof(GPUShaderExport), "GPUShaderExport");
- for (input = pass->inputs.first; input; input = input->next) {
+ for (input = mat->inputs.first; input; input = input->next) {
GPUInputUniform *uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform");
if (input->ima) {
@@ -2869,7 +2916,7 @@ void GPU_material_update_fvar_offset(GPUMaterial *gpu_material,
{
GPUPass *pass = gpu_material->pass;
GPUShader *shader = (pass != NULL ? pass->shader : NULL);
- ListBase *inputs = (pass != NULL ? &pass->inputs : NULL);
+ ListBase *inputs = (pass != NULL ? &gpu_material->inputs : NULL);
GPUInput *input;
if (shader == NULL) {
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index 153cf5f1e97..7023e44d289 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -73,7 +73,7 @@ static GPUSelectState g_select_state = {0};
/**
* initialize and provide buffer for results
*/
-void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const rcti *input, char mode, int oldhits)
+void GPU_select_begin(uint *buffer, uint bufsize, const rcti *input, char mode, int oldhits)
{
if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
/* In the case hits was '-1', don't start the second pass since it's not going to give useful results.
@@ -108,12 +108,12 @@ void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const rcti *in
case ALGO_GL_QUERY:
{
g_select_state.use_cache = false;
- gpu_select_query_begin((unsigned int (*)[4])buffer, bufsize / 4, input, mode, oldhits);
+ gpu_select_query_begin((uint (*)[4])buffer, bufsize / 4, input, mode, oldhits);
break;
}
default: /* ALGO_GL_PICK */
{
- gpu_select_pick_begin((unsigned int (*)[4])buffer, bufsize / 4, input, mode);
+ gpu_select_pick_begin((uint (*)[4])buffer, bufsize / 4, input, mode);
break;
}
}
@@ -126,7 +126,7 @@ void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const rcti *in
*
* \warning We rely on the order of object rendering on passes to be the same for this to work.
*/
-bool GPU_select_load_id(unsigned int id)
+bool GPU_select_load_id(uint id)
{
/* if no selection mode active, ignore */
if (!g_select_state.select_is_active)
@@ -154,9 +154,9 @@ bool GPU_select_load_id(unsigned int id)
* Return number of hits and hits in buffer.
* if \a dopass is true, we will do a second pass with occlusion queries to get the closest hit.
*/
-unsigned int GPU_select_end(void)
+uint GPU_select_end(void)
{
- unsigned int hits = 0;
+ uint hits = 0;
switch (g_select_state.algorithm) {
case ALGO_GL_LEGACY:
diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c
index f1d311890e6..4aef80934ad 100644
--- a/source/blender/gpu/intern/gpu_select_pick.c
+++ b/source/blender/gpu/intern/gpu_select_pick.c
@@ -62,14 +62,14 @@
/* For looping over a sub-region of a rect, could be moved into 'rct.c'*/
typedef struct SubRectStride {
- unsigned int start; /* start here */
- unsigned int span; /* read these */
- unsigned int span_len; /* len times (read span 'len' times). */
- unsigned int skip; /* skip those */
+ uint start; /* start here */
+ uint span; /* read these */
+ uint span_len; /* len times (read span 'len' times). */
+ uint skip; /* skip those */
} SubRectStride;
/* we may want to change back to float if uint isn't well supported */
-typedef unsigned int depth_t;
+typedef uint depth_t;
/**
* Calculate values needed for looping over a sub-region (smaller buffer within a larger buffer).
@@ -89,10 +89,10 @@ static void rect_subregion_stride_calc(const rcti *src, const rcti *dst, SubRect
src->ymax >= dst->ymax && src->ymax >= dst->ymax);
BLI_assert(x >= 0 && y >= 0);
- r_sub->start = (unsigned int)((src_x * y) + x);
- r_sub->span = (unsigned int)dst_x;
- r_sub->span_len = (unsigned int)dst_y;
- r_sub->skip = (unsigned int)(src_x - dst_x);
+ r_sub->start = (uint)((src_x * y) + x);
+ r_sub->span = (uint)dst_x;
+ r_sub->span_len = (uint)dst_y;
+ r_sub->skip = (uint)(src_x - dst_x);
}
/**
@@ -114,11 +114,11 @@ BLI_INLINE bool depth_is_filled(const depth_t *prev, const depth_t *curr)
/* store result of glReadPixels */
typedef struct DepthBufCache {
struct DepthBufCache *next, *prev;
- unsigned int id;
+ uint id;
depth_t buf[0];
} DepthBufCache;
-static DepthBufCache *depth_buf_malloc(unsigned int rect_len)
+static DepthBufCache *depth_buf_malloc(uint rect_len)
{
DepthBufCache *rect = MEM_mallocN(sizeof(DepthBufCache) + sizeof(depth_t) * rect_len, __func__);
rect->id = SELECT_ID_NONE;
@@ -127,10 +127,10 @@ static DepthBufCache *depth_buf_malloc(unsigned int rect_len)
static bool depth_buf_rect_depth_any(
const DepthBufCache *rect_depth,
- unsigned int rect_len)
+ uint rect_len)
{
const depth_t *curr = rect_depth->buf;
- for (unsigned int i = 0; i < rect_len; i++, curr++) {
+ for (uint i = 0; i < rect_len; i++, curr++) {
if (*curr != DEPTH_MAX) {
return true;
}
@@ -143,7 +143,7 @@ static bool depth_buf_subrect_depth_any(
const SubRectStride *sub_rect)
{
const depth_t *curr = rect_depth->buf + sub_rect->start;
- for (unsigned int i = 0; i < sub_rect->span_len; i++) {
+ for (uint i = 0; i < sub_rect->span_len; i++) {
const depth_t *curr_end = curr + sub_rect->span;
for (; curr < curr_end; curr++, curr++) {
if (*curr != DEPTH_MAX) {
@@ -157,14 +157,14 @@ static bool depth_buf_subrect_depth_any(
static bool depth_buf_rect_depth_any_filled(
const DepthBufCache *rect_prev, const DepthBufCache *rect_curr,
- unsigned int rect_len)
+ uint rect_len)
{
#if 0
return memcmp(rect_depth_a->buf, rect_depth_b->buf, rect_len * sizeof(depth_t)) != 0;
#else
const depth_t *prev = rect_prev->buf;
const depth_t *curr = rect_curr->buf;
- for (unsigned int i = 0; i < rect_len; i++, curr++, prev++) {
+ for (uint i = 0; i < rect_len; i++, curr++, prev++) {
if (depth_is_filled(prev, curr)) {
return true;
}
@@ -183,7 +183,7 @@ static bool depth_buf_subrect_depth_any_filled(
/* same as above but different rect sizes */
const depth_t *prev = rect_src->buf + sub_rect->start;
const depth_t *curr = rect_dst->buf + sub_rect->start;
- for (unsigned int i = 0; i < sub_rect->span_len; i++) {
+ for (uint i = 0; i < sub_rect->span_len; i++) {
const depth_t *curr_end = curr + sub_rect->span;
for (; curr < curr_end; prev++, curr++) {
if (depth_is_filled(prev, curr)) {
@@ -203,7 +203,7 @@ static bool depth_buf_subrect_depth_any_filled(
*/
typedef struct DepthID {
- unsigned int id;
+ uint id;
depth_t depth;
} DepthID;
@@ -238,10 +238,10 @@ static int depth_cmp(const void *v1, const void *v2)
/* depth sorting */
typedef struct GPUPickState {
/* cache on initialization */
- unsigned int (*buffer)[4];
+ uint (*buffer)[4];
/* buffer size (stores number of integers, for actual size multiply by sizeof integer)*/
- unsigned int bufsize;
+ uint bufsize;
/* mode of operation */
char mode;
@@ -257,14 +257,14 @@ typedef struct GPUPickState {
/* Set after first draw */
bool is_init;
- unsigned int prev_id;
+ uint prev_id;
} gl;
/* src: data stored in 'cache' and 'gl',
* dst: use when cached region is smaller (where src -> dst isn't 1:1) */
struct {
rcti clip_rect;
- unsigned int rect_len;
+ uint rect_len;
} src, dst;
/* Store cache between `GPU_select_cache_begin/end` */
@@ -284,13 +284,13 @@ typedef struct GPUPickState {
/* GPU_SELECT_PICK_ALL */
struct {
DepthID *hits;
- unsigned int hits_len;
- unsigned int hits_len_alloc;
+ uint hits_len;
+ uint hits_len_alloc;
} all;
/* GPU_SELECT_PICK_NEAREST */
struct {
- unsigned int *rect_id;
+ uint *rect_id;
} nearest;
};
} GPUPickState;
@@ -299,7 +299,7 @@ typedef struct GPUPickState {
static GPUPickState g_pick_state = {0};
void gpu_select_pick_begin(
- unsigned int (*buffer)[4], unsigned int bufsize,
+ uint (*buffer)[4], uint bufsize,
const rcti *input, char mode)
{
GPUPickState *ps = &g_pick_state;
@@ -312,7 +312,7 @@ void gpu_select_pick_begin(
ps->buffer = buffer;
ps->mode = mode;
- const unsigned int rect_len = (unsigned int)(BLI_rcti_size_x(input) * BLI_rcti_size_y(input));
+ const uint rect_len = (uint)(BLI_rcti_size_x(input) * BLI_rcti_size_y(input));
ps->dst.clip_rect = *input;
ps->dst.rect_len = rect_len;
@@ -327,6 +327,9 @@ void gpu_select_pick_begin(
glDepthMask(GL_TRUE);
if (mode == GPU_SELECT_PICK_ALL) {
+ /* Note that other depth settings (such as #GL_LEQUAL) work too,
+ * since the depth is always cleared.
+ * Noting this for cases when depth picking is used where drawing calls change depth settings. */
glDepthFunc(GL_ALWAYS);
}
else {
@@ -358,7 +361,7 @@ void gpu_select_pick_begin(
#if 0
glReadPixels(UNPACK4(ps->gl.clip_readpixels), GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, ps->gl.rect_depth->buf);
#else
- for (unsigned int i = 0; i < rect_len; i++) {
+ for (uint i = 0; i < rect_len; i++) {
ps->gl.rect_depth->buf[i] = DEPTH_MAX;
}
#endif
@@ -381,8 +384,8 @@ void gpu_select_pick_begin(
}
else {
/* Set to 0xff for SELECT_ID_NONE */
- ps->nearest.rect_id = MEM_mallocN(sizeof(unsigned int) * ps->dst.rect_len, __func__);
- memset(ps->nearest.rect_id, 0xff, sizeof(unsigned int) * ps->dst.rect_len);
+ ps->nearest.rect_id = MEM_mallocN(sizeof(uint) * ps->dst.rect_len, __func__);
+ memset(ps->nearest.rect_id, 0xff, sizeof(uint) * ps->dst.rect_len);
}
}
@@ -393,7 +396,7 @@ void gpu_select_pick_begin(
static void gpu_select_load_id_pass_all(const DepthBufCache *rect_curr)
{
GPUPickState *ps = &g_pick_state;
- const unsigned int id = rect_curr->id;
+ const uint id = rect_curr->id;
/* find the best depth for this pass and store in 'all.hits' */
depth_t depth_best = DEPTH_MAX;
@@ -405,15 +408,15 @@ static void gpu_select_load_id_pass_all(const DepthBufCache *rect_curr)
if (ps->is_cached == false) {
const depth_t *curr = rect_curr->buf;
BLI_assert(ps->src.rect_len == ps->dst.rect_len);
- const unsigned int rect_len = ps->src.rect_len;
- for (unsigned int i = 0; i < rect_len; i++, curr++) {
+ const uint rect_len = ps->src.rect_len;
+ for (uint i = 0; i < rect_len; i++, curr++) {
EVAL_TEST();
}
}
else {
/* same as above but different rect sizes */
const depth_t *curr = rect_curr->buf + ps->cache.sub_rect.start;
- for (unsigned int i = 0; i < ps->cache.sub_rect.span_len; i++) {
+ for (uint i = 0; i < ps->cache.sub_rect.span_len; i++) {
const depth_t *curr_end = curr + ps->cache.sub_rect.span;
for (; curr < curr_end; curr++) {
EVAL_TEST();
@@ -437,10 +440,10 @@ static void gpu_select_load_id_pass_all(const DepthBufCache *rect_curr)
static void gpu_select_load_id_pass_nearest(const DepthBufCache *rect_prev, const DepthBufCache *rect_curr)
{
GPUPickState *ps = &g_pick_state;
- const unsigned int id = rect_curr->id;
+ const uint id = rect_curr->id;
/* keep track each pixels ID in 'nearest.rect_id' */
if (id != SELECT_ID_NONE) {
- unsigned int *id_ptr = ps->nearest.rect_id;
+ uint *id_ptr = ps->nearest.rect_id;
/* Check against DEPTH_MAX because XRAY will clear the buffer,
* so previously set values will become unset.
@@ -454,8 +457,8 @@ static void gpu_select_load_id_pass_nearest(const DepthBufCache *rect_prev, cons
const depth_t *prev = rect_prev->buf;
const depth_t *curr = rect_curr->buf;
BLI_assert(ps->src.rect_len == ps->dst.rect_len);
- const unsigned int rect_len = ps->src.rect_len;
- for (unsigned int i = 0; i < rect_len; i++, curr++, prev++, id_ptr++) {
+ const uint rect_len = ps->src.rect_len;
+ for (uint i = 0; i < rect_len; i++, curr++, prev++, id_ptr++) {
EVAL_TEST();
}
}
@@ -463,7 +466,7 @@ static void gpu_select_load_id_pass_nearest(const DepthBufCache *rect_prev, cons
/* same as above but different rect sizes */
const depth_t *prev = rect_prev->buf + ps->cache.sub_rect.start;
const depth_t *curr = rect_curr->buf + ps->cache.sub_rect.start;
- for (unsigned int i = 0; i < ps->cache.sub_rect.span_len; i++) {
+ for (uint i = 0; i < ps->cache.sub_rect.span_len; i++) {
const depth_t *curr_end = curr + ps->cache.sub_rect.span;
for (; curr < curr_end; prev++, curr++, id_ptr++) {
EVAL_TEST();
@@ -478,11 +481,11 @@ static void gpu_select_load_id_pass_nearest(const DepthBufCache *rect_prev, cons
}
-bool gpu_select_pick_load_id(unsigned int id)
+bool gpu_select_pick_load_id(uint id)
{
GPUPickState *ps = &g_pick_state;
if (ps->gl.is_init) {
- const unsigned int rect_len = ps->src.rect_len;
+ const uint rect_len = ps->src.rect_len;
glReadPixels(UNPACK4(ps->gl.clip_readpixels), GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, ps->gl.rect_depth_test->buf);
/* perform initial check since most cases the array remains unchanged */
@@ -524,7 +527,7 @@ bool gpu_select_pick_load_id(unsigned int id)
return true;
}
-unsigned int gpu_select_pick_end(void)
+uint gpu_select_pick_end(void)
{
GPUPickState *ps = &g_pick_state;
@@ -537,7 +540,6 @@ unsigned int gpu_select_pick_end(void)
/* force finishing last pass */
gpu_select_pick_load_id(ps->gl.prev_id);
}
-
gpuPopAttrib();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
@@ -559,9 +561,9 @@ unsigned int gpu_select_pick_end(void)
rect_depth_final = ps->gl.rect_depth;
}
- unsigned int maxhits = g_pick_state.bufsize;
+ uint maxhits = g_pick_state.bufsize;
DepthID *depth_data;
- unsigned int depth_data_len = 0;
+ uint depth_data_len = 0;
if (g_pick_state.mode == GPU_SELECT_PICK_ALL) {
depth_data = ps->all.hits;
@@ -575,7 +577,7 @@ unsigned int gpu_select_pick_end(void)
/* GPU_SELECT_PICK_NEAREST */
/* Over alloc (unlikely we have as many depths as pixels) */
- unsigned int depth_data_len_first_pass = 0;
+ uint depth_data_len_first_pass = 0;
depth_data = MEM_mallocN(ps->dst.rect_len * sizeof(*depth_data), __func__);
/* Partially de-duplicating copy,
@@ -584,7 +586,7 @@ unsigned int gpu_select_pick_end(void)
#define EVAL_TEST(i_src, i_dst) \
{ \
- const unsigned int id = ps->nearest.rect_id[i_dst]; \
+ const uint id = ps->nearest.rect_id[i_dst]; \
if (id != SELECT_ID_NONE) { \
const depth_t depth = rect_depth_final->buf[i_src]; \
if (depth_last == NULL || depth_last->id != id) { \
@@ -601,15 +603,15 @@ unsigned int gpu_select_pick_end(void)
{
DepthID *depth_last = NULL;
if (ps->is_cached == false) {
- for (unsigned int i = 0; i < ps->src.rect_len; i++) {
+ for (uint i = 0; i < ps->src.rect_len; i++) {
EVAL_TEST(i, i);
}
}
else {
/* same as above but different rect sizes */
- unsigned int i_src = ps->cache.sub_rect.start, i_dst = 0;
- for (unsigned int j = 0; j < ps->cache.sub_rect.span_len; j++) {
- const unsigned int i_src_end = i_src + ps->cache.sub_rect.span;
+ uint i_src = ps->cache.sub_rect.start, i_dst = 0;
+ for (uint j = 0; j < ps->cache.sub_rect.span_len; j++) {
+ const uint i_src_end = i_src + ps->cache.sub_rect.span;
for (; i_src < i_src_end; i_src++, i_dst++) {
EVAL_TEST(i_src, i_dst);
}
@@ -626,7 +628,7 @@ unsigned int gpu_select_pick_end(void)
depth_data_len = 0;
{
DepthID *depth_last = NULL;
- for (unsigned int i = 0; i < depth_data_len_first_pass; i++) {
+ for (uint i = 0; i < depth_data_len_first_pass; i++) {
if (depth_last == NULL || depth_last->id != depth_data[i].id) {
depth_last = &depth_data[depth_data_len++];
*depth_last = depth_data[i];
@@ -640,16 +642,16 @@ unsigned int gpu_select_pick_end(void)
/* Finally sort each unique (id, depth) pair by depth
* so the final hit-list is sorted by depth (nearest first) */
- unsigned int hits = 0;
+ uint hits = 0;
if (depth_data_len > maxhits) {
- hits = (unsigned int)-1;
+ hits = (uint)-1;
}
else {
/* leave sorting up to the caller */
qsort(depth_data, depth_data_len, sizeof(DepthID), depth_cmp);
- for (unsigned int i = 0; i < depth_data_len; i++) {
+ for (uint i = 0; i < depth_data_len; i++) {
#ifdef DEBUG_PRINT
printf(" hit: %u: depth %u\n", depth_data[i].id, depth_data[i].depth);
#endif
diff --git a/source/blender/gpu/intern/gpu_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.c
index e3bd20f3776..12390e5cdb0 100644
--- a/source/blender/gpu/intern/gpu_select_sample_query.c
+++ b/source/blender/gpu/intern/gpu_select_sample_query.c
@@ -44,6 +44,8 @@
#include "BLI_utildefines.h"
+#include "PIL_time.h"
+
#include "gpu_select_private.h"
@@ -54,20 +56,20 @@ typedef struct GPUQueryState {
/* Tracks whether a query has been issued so that gpu_load_id can end the previous one */
bool query_issued;
/* array holding the OpenGL query identifiers */
- unsigned int *queries;
+ uint *queries;
/* array holding the id corresponding to each query */
- unsigned int *id;
+ uint *id;
/* number of queries in *queries and *id */
- unsigned int num_of_queries;
+ uint num_of_queries;
/* index to the next query to start */
- unsigned int active_query;
+ uint active_query;
/* cache on initialization */
- unsigned int (*buffer)[4];
+ uint (*buffer)[4];
/* buffer size (stores number of integers, for actual size multiply by sizeof integer)*/
- unsigned int bufsize;
+ uint bufsize;
/* mode of operation */
char mode;
- unsigned int index;
+ uint index;
int oldhits;
} GPUQueryState;
@@ -75,7 +77,7 @@ static GPUQueryState g_query_state = {0};
void gpu_select_query_begin(
- unsigned int (*buffer)[4], unsigned int bufsize,
+ uint (*buffer)[4], uint bufsize,
const rcti *input, char mode,
int oldhits)
{
@@ -96,7 +98,7 @@ void gpu_select_query_begin(
g_query_state.id = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.id), "gpu selection ids");
glGenQueries(g_query_state.num_of_queries, g_query_state.queries);
- gpuPushAttrib(GPU_DEPTH_BUFFER_BIT | GPU_VIEWPORT_BIT);
+ gpuPushAttrib(GPU_DEPTH_BUFFER_BIT | GPU_VIEWPORT_BIT | GPU_SCISSOR_BIT);
/* disable writing to the framebuffer */
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
@@ -114,6 +116,7 @@ void gpu_select_query_begin(
glDepthMask(GL_FALSE);
}
else if (mode == GPU_SELECT_NEAREST_FIRST_PASS) {
+ glDisable(GL_SCISSOR_TEST); /* allows fast clear */
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
@@ -126,7 +129,7 @@ void gpu_select_query_begin(
}
}
-bool gpu_select_query_load_id(unsigned int id)
+bool gpu_select_query_load_id(uint id)
{
if (g_query_state.query_issued) {
glEndQuery(GL_SAMPLES_PASSED);
@@ -161,19 +164,28 @@ bool gpu_select_query_load_id(unsigned int id)
return true;
}
-unsigned int gpu_select_query_end(void)
+uint gpu_select_query_end(void)
{
int i;
- unsigned int hits = 0;
- const unsigned int maxhits = g_query_state.bufsize;
+ uint hits = 0;
+ const uint maxhits = g_query_state.bufsize;
if (g_query_state.query_issued) {
glEndQuery(GL_SAMPLES_PASSED);
}
for (i = 0; i < g_query_state.active_query; i++) {
- unsigned int result;
+ uint result = 0;
+ /* Wait until the result is available. */
+ while (result == 0) {
+ glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT_AVAILABLE, &result);
+ if (result == 0) {
+ /* (fclem) Not sure if this is better than calling
+ * glGetQueryObjectuiv() indefinitely. */
+ PIL_sleep_ms(1);
+ }
+ }
glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT, &result);
if (result > 0) {
if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) {
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 598722d372b..e0b11edb197 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -37,7 +37,6 @@
#include "DNA_space_types.h"
-#include "GPU_compositing.h"
#include "GPU_extensions.h"
#include "GPU_matrix.h"
#include "GPU_shader.h"
@@ -66,17 +65,27 @@ extern char datatoc_gpu_shader_2D_flat_color_vert_glsl[];
extern char datatoc_gpu_shader_2D_smooth_color_vert_glsl[];
extern char datatoc_gpu_shader_2D_smooth_color_frag_glsl[];
extern char datatoc_gpu_shader_2D_image_vert_glsl[];
+extern char datatoc_gpu_shader_2D_image_rect_vert_glsl[];
+extern char datatoc_gpu_shader_2D_image_multi_rect_vert_glsl[];
+extern char datatoc_gpu_shader_2D_widget_base_vert_glsl[];
+extern char datatoc_gpu_shader_2D_widget_base_frag_glsl[];
+extern char datatoc_gpu_shader_2D_widget_shadow_vert_glsl[];
+extern char datatoc_gpu_shader_2D_widget_shadow_frag_glsl[];
+extern char datatoc_gpu_shader_2D_nodelink_frag_glsl[];
+extern char datatoc_gpu_shader_2D_nodelink_vert_glsl[];
extern char datatoc_gpu_shader_3D_image_vert_glsl[];
+extern char datatoc_gpu_shader_image_frag_glsl[];
extern char datatoc_gpu_shader_image_linear_frag_glsl[];
extern char datatoc_gpu_shader_image_color_frag_glsl[];
+extern char datatoc_gpu_shader_image_varying_color_frag_glsl[];
extern char datatoc_gpu_shader_image_alpha_color_frag_glsl[];
extern char datatoc_gpu_shader_image_shuffle_color_frag_glsl[];
extern char datatoc_gpu_shader_image_interlace_frag_glsl[];
extern char datatoc_gpu_shader_image_mask_uniform_color_frag_glsl[];
extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[];
-extern char datatoc_gpu_shader_image_rect_modulate_alpha_frag_glsl[];
extern char datatoc_gpu_shader_image_depth_linear_frag_glsl[];
+extern char datatoc_gpu_shader_image_depth_copy_frag_glsl[];
extern char datatoc_gpu_shader_3D_vert_glsl[];
extern char datatoc_gpu_shader_3D_normal_vert_glsl[];
extern char datatoc_gpu_shader_3D_flat_color_vert_glsl[];
@@ -98,7 +107,7 @@ extern char datatoc_gpu_shader_instance_edges_variying_color_geom_glsl[];
extern char datatoc_gpu_shader_instance_edges_variying_color_vert_glsl[];
extern char datatoc_gpu_shader_instance_bone_envelope_solid_vert_glsl[];
extern char datatoc_gpu_shader_instance_bone_envelope_wire_vert_glsl[];
-extern char datatoc_gpu_shader_instance_mball_helpers_vert_glsl[];
+extern char datatoc_gpu_shader_instance_mball_handles_vert_glsl[];
extern char datatoc_gpu_shader_3D_groundpoint_vert_glsl[];
extern char datatoc_gpu_shader_3D_groundline_geom_glsl[];
@@ -133,7 +142,10 @@ extern char datatoc_gpu_shader_edges_overlay_geom_glsl[];
extern char datatoc_gpu_shader_edges_overlay_simple_geom_glsl[];
extern char datatoc_gpu_shader_edges_overlay_frag_glsl[];
extern char datatoc_gpu_shader_text_vert_glsl[];
+extern char datatoc_gpu_shader_text_geom_glsl[];
extern char datatoc_gpu_shader_text_frag_glsl[];
+extern char datatoc_gpu_shader_text_simple_vert_glsl[];
+extern char datatoc_gpu_shader_text_simple_geom_glsl[];
extern char datatoc_gpu_shader_keyframe_diamond_vert_glsl[];
extern char datatoc_gpu_shader_keyframe_diamond_frag_glsl[];
@@ -144,22 +156,10 @@ extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[];
-extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
-extern char datatoc_gpu_shader_fx_ssao_frag_glsl[];
-extern char datatoc_gpu_shader_fx_dof_frag_glsl[];
-extern char datatoc_gpu_shader_fx_dof_vert_glsl[];
-extern char datatoc_gpu_shader_fx_dof_hq_frag_glsl[];
-extern char datatoc_gpu_shader_fx_dof_hq_vert_glsl[];
-extern char datatoc_gpu_shader_fx_dof_hq_geo_glsl[];
-extern char datatoc_gpu_shader_fx_depth_resolve_glsl[];
-extern char datatoc_gpu_shader_fx_lib_glsl[];
/* cache of built-in shaders (each is created on first use) */
static GPUShader *builtin_shaders[GPU_NUM_BUILTIN_SHADERS] = { NULL };
-/* cache for shader fx. Those can exist in combinations so store them here */
-static GPUShader *fx_shaders[MAX_FX_SHADERS * 2] = { NULL };
-
typedef struct {
const char *vert;
const char *frag;
@@ -542,9 +542,6 @@ void GPU_shader_free(GPUShader *shader)
if (shader->program)
glDeleteProgram(shader->program);
- if (shader->uniform_interface)
- MEM_freeN(shader->uniform_interface);
-
if (shader->interface)
GWN_shaderinterface_discard(shader->interface);
@@ -573,11 +570,6 @@ int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
return ubo ? ubo->location : -1;
}
-void *GPU_fx_shader_get_interface(GPUShader *shader)
-{
- return shader->uniform_interface;
-}
-
void *GPU_shader_get_interface(GPUShader *shader)
{
return shader->interface;
@@ -589,11 +581,6 @@ int GPU_shader_get_program(GPUShader *shader)
return (int)shader->program;
}
-void GPU_fx_shader_set_interface(GPUShader *shader, void *interface)
-{
- shader->uniform_interface = interface;
-}
-
void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
{
if (location == -1 || value == NULL)
@@ -640,32 +627,17 @@ void GPU_shader_uniform_buffer(GPUShader *shader, int location, GPUUniformBuffer
void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
{
int number = GPU_texture_bound_number(tex);
- int bindcode = GPU_texture_opengl_bindcode(tex);
- int target = GPU_texture_target(tex);
- if (number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
+ if (number == -1) {
+ fprintf(stderr, "Texture is not bound.\n");
+ BLI_assert(0);
return;
}
-
- if (number == -1)
- return;
if (location == -1)
return;
- if (number != 0)
- glActiveTexture(GL_TEXTURE0 + number);
-
- if (bindcode != 0)
- glBindTexture(target, bindcode);
- else
- GPU_invalid_tex_bind(target);
-
glUniform1i(location, number);
-
- if (number != 0)
- glActiveTexture(GL_TEXTURE0);
}
int GPU_shader_get_attribute(GPUShader *shader, const char *name)
@@ -687,7 +659,12 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
[GPU_SHADER_SMOKE_FIRE] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl },
[GPU_SHADER_SMOKE_COBA] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl },
- [GPU_SHADER_TEXT] = { datatoc_gpu_shader_text_vert_glsl, datatoc_gpu_shader_text_frag_glsl },
+ [GPU_SHADER_TEXT] = { datatoc_gpu_shader_text_vert_glsl,
+ datatoc_gpu_shader_text_frag_glsl,
+ datatoc_gpu_shader_text_geom_glsl },
+ [GPU_SHADER_TEXT_SIMPLE] = { datatoc_gpu_shader_text_simple_vert_glsl,
+ datatoc_gpu_shader_text_frag_glsl,
+ datatoc_gpu_shader_text_simple_geom_glsl },
[GPU_SHADER_KEYFRAME_DIAMOND] = { datatoc_gpu_shader_keyframe_diamond_vert_glsl,
datatoc_gpu_shader_keyframe_diamond_frag_glsl },
[GPU_SHADER_EDGES_FRONT_BACK_PERSP] = { datatoc_gpu_shader_edges_front_back_persp_vert_glsl,
@@ -710,10 +687,10 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
datatoc_gpu_shader_image_mask_uniform_color_frag_glsl },
[GPU_SHADER_3D_IMAGE_MODULATE_ALPHA] = { datatoc_gpu_shader_3D_image_vert_glsl,
datatoc_gpu_shader_image_modulate_alpha_frag_glsl },
- [GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA] = { datatoc_gpu_shader_3D_image_vert_glsl,
- datatoc_gpu_shader_image_rect_modulate_alpha_frag_glsl },
[GPU_SHADER_3D_IMAGE_DEPTH] = { datatoc_gpu_shader_3D_image_vert_glsl,
datatoc_gpu_shader_image_depth_linear_frag_glsl },
+ [GPU_SHADER_3D_IMAGE_DEPTH_COPY] = { datatoc_gpu_shader_3D_image_vert_glsl,
+ datatoc_gpu_shader_image_depth_copy_frag_glsl },
[GPU_SHADER_2D_IMAGE_INTERLACE] = { datatoc_gpu_shader_2D_image_vert_glsl,
datatoc_gpu_shader_image_interlace_frag_glsl },
@@ -728,12 +705,21 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
datatoc_gpu_shader_2D_smooth_color_frag_glsl },
[GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB] = { datatoc_gpu_shader_2D_image_vert_glsl,
datatoc_gpu_shader_image_linear_frag_glsl },
+ [GPU_SHADER_2D_IMAGE] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_frag_glsl },
[GPU_SHADER_2D_IMAGE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
datatoc_gpu_shader_image_color_frag_glsl },
[GPU_SHADER_2D_IMAGE_ALPHA_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
datatoc_gpu_shader_image_alpha_color_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_ALPHA] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_modulate_alpha_frag_glsl },
[GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
datatoc_gpu_shader_image_shuffle_color_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_RECT_COLOR] = { datatoc_gpu_shader_2D_image_rect_vert_glsl,
+ datatoc_gpu_shader_image_color_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR] = { datatoc_gpu_shader_2D_image_multi_rect_vert_glsl,
+ datatoc_gpu_shader_image_varying_color_frag_glsl },
+
[GPU_SHADER_3D_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
[GPU_SHADER_3D_UNIFORM_COLOR_U32] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
[GPU_SHADER_3D_FLAT_COLOR] = { datatoc_gpu_shader_3D_flat_color_vert_glsl,
@@ -816,12 +802,23 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
datatoc_gpu_shader_flat_color_frag_glsl,
datatoc_gpu_shader_instance_edges_variying_color_geom_glsl},
+ [GPU_SHADER_2D_WIDGET_BASE] = { datatoc_gpu_shader_2D_widget_base_vert_glsl,
+ datatoc_gpu_shader_2D_widget_base_frag_glsl},
+ [GPU_SHADER_2D_WIDGET_BASE_INST] = { datatoc_gpu_shader_2D_widget_base_vert_glsl,
+ datatoc_gpu_shader_2D_widget_base_frag_glsl},
+ [GPU_SHADER_2D_WIDGET_SHADOW] = { datatoc_gpu_shader_2D_widget_shadow_vert_glsl,
+ datatoc_gpu_shader_2D_widget_shadow_frag_glsl },
+ [GPU_SHADER_2D_NODELINK] = { datatoc_gpu_shader_2D_nodelink_vert_glsl,
+ datatoc_gpu_shader_2D_nodelink_frag_glsl },
+ [GPU_SHADER_2D_NODELINK_INST] = { datatoc_gpu_shader_2D_nodelink_vert_glsl,
+ datatoc_gpu_shader_2D_nodelink_frag_glsl },
+
[GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID] = { datatoc_gpu_shader_instance_bone_envelope_solid_vert_glsl,
datatoc_gpu_shader_simple_lighting_frag_glsl },
[GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_WIRE] = { datatoc_gpu_shader_instance_bone_envelope_wire_vert_glsl,
datatoc_gpu_shader_flat_color_frag_glsl },
- [GPU_SHADER_3D_INSTANCE_MBALL_HELPERS] = { datatoc_gpu_shader_instance_mball_helpers_vert_glsl,
+ [GPU_SHADER_3D_INSTANCE_MBALL_HANDLES] = { datatoc_gpu_shader_instance_mball_handles_vert_glsl,
datatoc_gpu_shader_flat_color_frag_glsl },
};
@@ -829,25 +826,29 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
/* just a few special cases */
const char *defines = NULL;
switch (shader) {
+ case GPU_SHADER_2D_WIDGET_BASE_INST:
+ case GPU_SHADER_2D_NODELINK_INST:
+ defines = "#define USE_INSTANCE\n";
+ break;
case GPU_SHADER_SMOKE_COBA:
- defines = "#define USE_COBA;\n";
+ defines = "#define USE_COBA\n";
break;
case GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE:
- defines = "#define UNIFORM_SCALE;\n";
+ defines = "#define UNIFORM_SCALE\n";
break;
case GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS:
- defines = "#define AXIS_NAME;\n";
+ defines = "#define AXIS_NAME\n";
break;
case GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR:
case GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID:
- defines = "#define USE_INSTANCE_COLOR;\n";
+ defines = "#define USE_INSTANCE_COLOR\n";
break;
case GPU_SHADER_3D_FLAT_COLOR_U32:
case GPU_SHADER_3D_UNIFORM_COLOR_U32:
- defines = "#define USE_COLOR_U32;\n";
+ defines = "#define USE_COLOR_U32\n";
break;
case GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR:
- defines = "#define USE_FLAT_NORMAL;\n";
+ defines = "#define USE_FLAT_NORMAL\n";
break;
default:
break;
@@ -880,82 +881,6 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
#define MAX_DEFINES 100
-GPUShader *GPU_shader_get_builtin_fx_shader(int effect, bool persp)
-{
- int offset;
- char defines[MAX_DEFINES] = "";
- /* avoid shaders out of range */
- if (effect >= MAX_FX_SHADERS)
- return NULL;
-
- offset = 2 * effect;
-
- if (persp) {
- offset += 1;
- strcat(defines, "#define PERSP_MATRIX\n");
- }
-
- if (!fx_shaders[offset]) {
- GPUShader *shader = NULL;
-
- switch (effect) {
- case GPU_SHADER_FX_SSAO:
- shader = GPU_shader_create(datatoc_gpu_shader_fullscreen_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
- strcat(defines, "#define FIRST_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
- strcat(defines, "#define SECOND_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
- strcat(defines, "#define THIRD_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
- strcat(defines, "#define FOURTH_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
- strcat(defines, "#define FIFTH_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
- strcat(defines, "#define FIRST_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
- strcat(defines, "#define SECOND_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
- strcat(defines, "#define THIRD_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_RESOLVE:
- shader = GPU_shader_create(datatoc_gpu_shader_fullscreen_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines);
- break;
- }
-
- fx_shaders[offset] = shader;
- GPU_fx_shader_init_interface(shader, effect);
- }
-
- return fx_shaders[offset];
-}
-
-
void GPU_shader_free_builtin_shaders(void)
{
for (int i = 0; i < GPU_NUM_BUILTIN_SHADERS; ++i) {
@@ -964,11 +889,4 @@ void GPU_shader_free_builtin_shaders(void)
builtin_shaders[i] = NULL;
}
}
-
- for (int i = 0; i < 2 * MAX_FX_SHADERS; ++i) {
- if (fx_shaders[i]) {
- GPU_shader_free(fx_shaders[i]);
- fx_shaders[i] = NULL;
- }
- }
}
diff --git a/source/blender/gpu/intern/gpu_shader_private.h b/source/blender/gpu/intern/gpu_shader_private.h
index f883773df17..67d8c6e6213 100644
--- a/source/blender/gpu/intern/gpu_shader_private.h
+++ b/source/blender/gpu/intern/gpu_shader_private.h
@@ -35,9 +35,6 @@ struct GPUShader {
GLuint geometry; /* handle for geometry shader */
GLuint fragment; /* handle for fragment shader */
- void *uniform_interface; /* cached uniform interface for shader. Data depends on shader */
- /* NOTE: ^-- only FX compositing shaders use this */
-
Gwn_ShaderInterface *interface; /* cached uniform & attrib interface for shader */
};
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index d6b641af225..75830f60f03 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -48,6 +48,22 @@ static struct GPUTextureGlobal {
GPUTexture *invalid_tex_3D;
} GG = {NULL, NULL, NULL};
+/* Maximum number of FBOs a texture can be attached to. */
+#define GPU_TEX_MAX_FBO_ATTACHED 8
+
+typedef enum GPUTextureFormatFlag{
+ GPU_FORMAT_DEPTH = (1 << 0),
+ GPU_FORMAT_STENCIL = (1 << 1),
+ GPU_FORMAT_INTEGER = (1 << 2),
+ GPU_FORMAT_FLOAT = (1 << 3),
+
+ GPU_FORMAT_1D = (1 << 10),
+ GPU_FORMAT_2D = (1 << 11),
+ GPU_FORMAT_3D = (1 << 12),
+ GPU_FORMAT_CUBE = (1 << 13),
+ GPU_FORMAT_ARRAY = (1 << 14),
+} GPUTextureFormatFlag;
+
/* GPUTexture */
struct GPUTexture {
int w, h, d; /* width/height/depth */
@@ -59,14 +75,15 @@ struct GPUTexture {
GLuint bindcode; /* opengl identifier for texture */
int fromblender; /* we got the texture from Blender */
- GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
- int fb_attachment; /* slot the texture is attached to */
- bool depth; /* is a depth texture? */
- bool stencil; /* is a stencil texture? */
+ GPUTextureFormat format;
+ GPUTextureFormatFlag format_flag;
unsigned int bytesize; /* number of byte for one pixel */
- int format; /* GPUTextureFormat */
int components; /* number of color/alpha channels */
+ int samples; /* number of samples for multisamples textures. 0 if not multisample target */
+
+ int fb_attachment[GPU_TEX_MAX_FBO_ATTACHED];
+ GPUFrameBuffer *fb[GPU_TEX_MAX_FBO_ATTACHED];
};
/* ------ Memory Management ------- */
@@ -113,30 +130,26 @@ unsigned int GPU_texture_memory_usage_get(void)
static GLenum gpu_texture_get_format(
int components, GPUTextureFormat data_type,
- GLenum *format, GLenum *data_format, bool *is_depth, bool *is_stencil, unsigned int *bytesize)
+ GLenum *format, GLenum *data_format, GPUTextureFormatFlag *format_flag, unsigned int *bytesize)
{
if (ELEM(data_type, GPU_DEPTH_COMPONENT24,
GPU_DEPTH_COMPONENT16,
GPU_DEPTH_COMPONENT32F))
{
- *is_depth = true;
- *is_stencil = false;
+ *format_flag |= GPU_FORMAT_DEPTH;
*data_format = GL_FLOAT;
*format = GL_DEPTH_COMPONENT;
}
else if (data_type == GPU_DEPTH24_STENCIL8) {
- *is_depth = true;
- *is_stencil = true;
+ *format_flag |= GPU_FORMAT_DEPTH | GPU_FORMAT_STENCIL;
*data_format = GL_UNSIGNED_INT_24_8;
*format = GL_DEPTH_STENCIL;
}
else {
- *is_depth = false;
- *is_stencil = false;
-
/* Integer formats */
- if (ELEM(data_type, GPU_RG16I)) {
+ if (ELEM(data_type, GPU_RG16I, GPU_R16I)) {
*data_format = GL_INT;
+ *format_flag |= GPU_FORMAT_INTEGER;
switch (components) {
case 1: *format = GL_RED_INTEGER; break;
@@ -148,6 +161,7 @@ static GLenum gpu_texture_get_format(
}
else {
*data_format = GL_FLOAT;
+ *format_flag |= GPU_FORMAT_FLOAT;
switch (components) {
case 1: *format = GL_RED; break;
@@ -184,6 +198,7 @@ static GLenum gpu_texture_get_format(
break;
case GPU_DEPTH_COMPONENT16:
case GPU_R16F:
+ case GPU_R16I:
case GPU_RG8:
*bytesize = 2;
break;
@@ -208,6 +223,7 @@ static GLenum gpu_texture_get_format(
case GPU_RGBA8: return GL_RGBA8;
case GPU_R32F: return GL_R32F;
case GPU_R16F: return GL_R16F;
+ case GPU_R16I: return GL_R16I;
case GPU_RG8: return GL_RG8;
case GPU_R8: return GL_R8;
/* Special formats texture & renderbuffer */
@@ -340,11 +356,12 @@ static GPUTexture *GPU_texture_create_nD(
tex->w = w;
tex->h = h;
tex->d = d;
+ tex->samples = samples;
tex->number = -1;
tex->refcount = 1;
- tex->fb_attachment = -1;
tex->format = data_type;
tex->components = components;
+ tex->format_flag = 0;
if (n == 2) {
if (d == 0)
@@ -371,7 +388,8 @@ static GPUTexture *GPU_texture_create_nD(
tex->target = GL_TEXTURE_2D_MULTISAMPLE;
GLenum format, internalformat, data_format;
- internalformat = gpu_texture_get_format(components, data_type, &format, &data_format, &tex->depth, &tex->stencil, &tex->bytesize);
+ internalformat = gpu_texture_get_format(components, data_type, &format, &data_format,
+ &tex->format_flag, &tex->bytesize);
gpu_texture_memory_footprint_add(tex);
@@ -387,7 +405,6 @@ static GPUTexture *GPU_texture_create_nD(
return NULL;
}
- tex->number = 0;
glBindTexture(tex->target, tex->bindcode);
/* Check if texture fit in VRAM */
@@ -446,17 +463,23 @@ static GPUTexture *GPU_texture_create_nD(
MEM_freeN(rescaled_fpixels);
/* Texture Parameters */
- if (tex->depth) {
+ if (GPU_texture_stencil(tex) || /* Does not support filtering */
+ GPU_texture_integer(tex) || /* Does not support filtering */
+ GPU_texture_depth(tex))
+ {
glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
else {
glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
+ if (GPU_texture_depth(tex)) {
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ }
+
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
if (n > 1) {
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -465,7 +488,7 @@ static GPUTexture *GPU_texture_create_nD(
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
}
- GPU_texture_unbind(tex);
+ glBindTexture(tex->target, 0);
return tex;
}
@@ -483,11 +506,12 @@ static GPUTexture *GPU_texture_cube_create(
tex->w = w;
tex->h = w;
tex->d = d;
+ tex->samples = 0;
tex->number = -1;
tex->refcount = 1;
- tex->fb_attachment = -1;
tex->format = data_type;
tex->components = components;
+ tex->format_flag = GPU_FORMAT_CUBE;
if (d == 0) {
tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP;
@@ -497,7 +521,8 @@ static GPUTexture *GPU_texture_cube_create(
// tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP_ARRAY;
}
- internalformat = gpu_texture_get_format(components, data_type, &format, &data_format, &tex->depth, &tex->stencil, &tex->bytesize);
+ internalformat = gpu_texture_get_format(components, data_type, &format, &data_format,
+ &tex->format_flag, &tex->bytesize);
gpu_texture_memory_footprint_add(tex);
@@ -513,7 +538,6 @@ static GPUTexture *GPU_texture_cube_create(
return NULL;
}
- tex->number = 0;
glBindTexture(tex->target, tex->bindcode);
/* Upload Texture */
@@ -525,22 +549,28 @@ static GPUTexture *GPU_texture_cube_create(
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, tex->w, tex->h, 0, format, data_format, fpixels_nz);
/* Texture Parameters */
- if (tex->depth) {
+ if (GPU_texture_stencil(tex) || /* Does not support filtering */
+ GPU_texture_integer(tex) || /* Does not support filtering */
+ GPU_texture_depth(tex))
+ {
glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
else {
glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
+ if (GPU_texture_depth(tex)) {
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ }
+
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
- GPU_texture_unbind(tex);
+ glBindTexture(tex->target, 0);
return tex;
}
@@ -576,6 +606,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
tex->fromblender = 1;
tex->format = -1;
tex->components = -1;
+ tex->samples = 0;
ima->gputexture[gputt] = tex;
@@ -686,7 +717,8 @@ GPUTexture *GPU_texture_create_2D_custom_multisample(
return GPU_texture_create_nD(w, h, 0, 2, pixels, data_type, channels, samples, false, err_out);
}
-GPUTexture *GPU_texture_create_2D_array_custom(int w, int h, int d, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256])
+GPUTexture *GPU_texture_create_2D_array_custom(
+ int w, int h, int d, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256])
{
return GPU_texture_create_nD(w, h, d, 2, pixels, data_type, channels, 0, false, err_out);
}
@@ -696,11 +728,13 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int d, const float *pixels, char
return GPU_texture_create_nD(w, h, d, 3, pixels, GPU_RGBA8, 4, 0, true, err_out);
}
-GPUTexture *GPU_texture_create_3D_custom(int w, int h, int d, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256])
+GPUTexture *GPU_texture_create_3D_custom(
+ int w, int h, int d, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256])
{
return GPU_texture_create_nD(w, h, d, 3, pixels, data_type, channels, 0, true, err_out);
}
-GPUTexture *GPU_texture_create_cube_custom(int w, int channels, GPUTextureFormat data_type, const float *fpixels, char err_out[256])
+GPUTexture *GPU_texture_create_cube_custom(
+ int w, int channels, GPUTextureFormat data_type, const float *fpixels, char err_out[256])
{
const float *fpixels_px, *fpixels_py, *fpixels_pz, *fpixels_nx, *fpixels_ny, *fpixels_nz;
@@ -716,7 +750,8 @@ GPUTexture *GPU_texture_create_cube_custom(int w, int channels, GPUTextureFormat
fpixels_px = fpixels_py = fpixels_pz = fpixels_nx = fpixels_ny = fpixels_nz = NULL;
}
- return GPU_texture_cube_create(w, 0, fpixels_px, fpixels_py, fpixels_pz, fpixels_nx, fpixels_ny, fpixels_nz, data_type, channels, err_out);
+ return GPU_texture_cube_create(w, 0, fpixels_px, fpixels_py, fpixels_pz, fpixels_nx, fpixels_ny, fpixels_nz,
+ data_type, channels, err_out);
}
GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
@@ -745,7 +780,8 @@ void GPU_texture_update(GPUTexture *tex, const float *pixels)
BLI_assert(tex->components > -1);
GLenum format, data_format;
- gpu_texture_get_format(tex->components, tex->format, &format, &data_format, &tex->depth, &tex->stencil, &tex->bytesize);
+ gpu_texture_get_format(tex->components, tex->format, &format, &data_format,
+ &tex->format_flag, &tex->bytesize);
glBindTexture(tex->target, tex->bindcode);
@@ -803,55 +839,44 @@ void GPU_invalid_tex_free(void)
GPU_texture_free(GG.invalid_tex_3D);
}
-
void GPU_texture_bind(GPUTexture *tex, int number)
{
+ BLI_assert(number >= 0);
+
if (number >= GPU_max_textures()) {
fprintf(stderr, "Not enough texture slots.\n");
return;
}
if ((G.debug & G_DEBUG)) {
- if (tex->fb && GPU_framebuffer_bound(tex->fb)) {
- fprintf(stderr, "Feedback loop warning!: Attempting to bind texture attached to current framebuffer!\n");
+ for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
+ if (tex->fb[i] && GPU_framebuffer_bound(tex->fb[i])) {
+ fprintf(stderr, "Feedback loop warning!: Attempting to bind "
+ "texture attached to current framebuffer!\n");
+ BLI_assert(0); /* Should never happen! */
+ break;
+ }
}
}
- if (number < 0)
- return;
-
- if (number != 0)
- glActiveTexture(GL_TEXTURE0 + number);
+ glActiveTexture(GL_TEXTURE0 + number);
if (tex->bindcode != 0)
glBindTexture(tex->target, tex->bindcode);
else
GPU_invalid_tex_bind(tex->target_base);
- if (number != 0)
- glActiveTexture(GL_TEXTURE0);
-
tex->number = number;
}
void GPU_texture_unbind(GPUTexture *tex)
{
- if (tex->number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
-
if (tex->number == -1)
return;
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0 + tex->number);
-
+ glActiveTexture(GL_TEXTURE0 + tex->number);
glBindTexture(tex->target, 0);
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0);
-
tex->number = -1;
}
@@ -860,114 +885,79 @@ int GPU_texture_bound_number(GPUTexture *tex)
return tex->number;
}
+#define WARN_NOT_BOUND(_tex) do { \
+ if (_tex->number == -1) { \
+ fprintf(stderr, "Warning : Trying to set parameter on a texture not bound.\n"); \
+ BLI_assert(0); \
+ return; \
+ } \
+} while (0);
+
void GPU_texture_generate_mipmap(GPUTexture *tex)
{
- if (tex->number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
-
- if (tex->number == -1)
- return;
-
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0 + tex->number);
+ WARN_NOT_BOUND(tex);
+ glActiveTexture(GL_TEXTURE0 + tex->number);
glGenerateMipmap(tex->target_base);
-
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0);
}
void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare)
{
- if (tex->number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
+ WARN_NOT_BOUND(tex);
- if (tex->number == -1)
+ /* Could become an assertion ? (fclem) */
+ if (!GPU_texture_depth(tex))
return;
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0 + tex->number);
-
- /* TODO viewport: use GL_COMPARE_REF_TO_TEXTURE after we switch to core profile */
- if (tex->depth)
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, use_compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE);
+ GLenum mode = (use_compare) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE;
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, mode);
}
void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter)
{
- if (tex->number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
+ WARN_NOT_BOUND(tex);
- if (tex->number == -1)
- return;
+ /* Stencil and integer format does not support filtering. */
+ BLI_assert(!use_filter || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0 + tex->number);
+ GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST;
- GLenum filter = use_filter ? GL_LINEAR : GL_NEAREST;
+ glActiveTexture(GL_TEXTURE0 + tex->number);
glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, filter);
-
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0);
}
void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter)
{
- if (tex->number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
-
- if (tex->number == -1)
- return;
+ WARN_NOT_BOUND(tex);
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0 + tex->number);
+ /* Stencil and integer format does not support filtering. */
+ BLI_assert((!use_filter && !use_mipmap) || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
+ GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST;
GLenum mipmap = (use_filter)
- ? use_mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR
- : use_mipmap ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST;
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, mipmap);
+ ? (use_mipmap) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR
+ : (use_mipmap) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST;
- GLenum filter = use_filter ? GL_LINEAR : GL_NEAREST;
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, mipmap);
glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
-
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0);
}
void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat)
{
- if (tex->number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
+ WARN_NOT_BOUND(tex);
- if (tex->number == -1)
- return;
-
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0 + tex->number);
+ GLenum repeat = (use_repeat) ? GL_REPEAT : GL_CLAMP_TO_EDGE;
- GLenum repeat = use_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE;
+ glActiveTexture(GL_TEXTURE0 + tex->number);
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, repeat);
if (tex->target_base != GL_TEXTURE_1D)
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, repeat);
if (tex->target_base == GL_TEXTURE_3D)
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, repeat);
-
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0);
}
void GPU_texture_free(GPUTexture *tex)
@@ -978,8 +968,12 @@ void GPU_texture_free(GPUTexture *tex)
fprintf(stderr, "GPUTexture: negative refcount\n");
if (tex->refcount == 0) {
- if (tex->fb)
- GPU_framebuffer_texture_detach(tex);
+ for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
+ if (tex->fb[i] != NULL) {
+ GPU_framebuffer_texture_detach_slot(tex->fb[i], tex, tex->fb_attachment[i]);
+ }
+ }
+
if (tex->bindcode && !tex->fromblender)
glDeleteTextures(1, &tex->bindcode);
@@ -1009,39 +1003,64 @@ int GPU_texture_height(const GPUTexture *tex)
return tex->h;
}
-int GPU_texture_format(const GPUTexture *tex)
+GPUTextureFormat GPU_texture_format(const GPUTexture *tex)
{
return tex->format;
}
+int GPU_texture_samples(const GPUTexture *tex)
+{
+ return tex->samples;
+}
+
bool GPU_texture_depth(const GPUTexture *tex)
{
- return tex->depth;
+ return (tex->format_flag & GPU_FORMAT_DEPTH) != 0;
}
bool GPU_texture_stencil(const GPUTexture *tex)
{
- return tex->stencil;
+ return (tex->format_flag & GPU_FORMAT_STENCIL) != 0;
}
-int GPU_texture_opengl_bindcode(const GPUTexture *tex)
+bool GPU_texture_integer(const GPUTexture *tex)
{
- return tex->bindcode;
+ return (tex->format_flag & GPU_FORMAT_INTEGER) != 0;
}
-GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
+bool GPU_texture_cube(const GPUTexture *tex)
{
- return tex->fb;
+ return (tex->format_flag & GPU_FORMAT_CUBE) != 0;
}
-int GPU_texture_framebuffer_attachment(GPUTexture *tex)
+int GPU_texture_opengl_bindcode(const GPUTexture *tex)
{
- return tex->fb_attachment;
+ return tex->bindcode;
}
-void GPU_texture_framebuffer_set(GPUTexture *tex, GPUFrameBuffer *fb, int attachment)
+void GPU_texture_attach_framebuffer(GPUTexture *tex, GPUFrameBuffer *fb, int attachment)
{
- tex->fb = fb;
- tex->fb_attachment = attachment;
+ for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
+ if (tex->fb[i] == NULL) {
+ tex->fb[i] = fb;
+ tex->fb_attachment[i] = attachment;
+ return;
+ }
+ }
+
+ BLI_assert(!"Error: Texture: Not enough Framebuffer slots");
}
+/* Return previous attachment point */
+int GPU_texture_detach_framebuffer(GPUTexture *tex, GPUFrameBuffer *fb)
+{
+ for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
+ if (tex->fb[i] == fb) {
+ tex->fb[i] = NULL;
+ return tex->fb_attachment[i];
+ }
+ }
+
+ BLI_assert(!"Error: Texture: Framebuffer is not attached");
+ return 0;
+}
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index 3ef53b3a6c3..5d89bd59277 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -48,6 +48,7 @@
#include "GPU_immediate.h"
#include "GPU_texture.h"
#include "GPU_viewport.h"
+#include "GPU_draw.h"
#include "DRW_engine.h"
@@ -68,12 +69,7 @@ typedef struct ViewportTempTexture {
} ViewportTempTexture;
struct GPUViewport {
- float pad[4];
-
- /* debug */
- GPUTexture *debug_depth;
int size[2];
-
int samples;
int flag;
@@ -87,6 +83,9 @@ struct GPUViewport {
struct DRWInstanceDataList *idatalist; /* Used for rendering data structure. */
ListBase tex_pool; /* ViewportTempTexture list : Temporary textures shared across draw engines */
+
+ /* Profiling data */
+ double cache_time;
};
enum {
@@ -97,6 +96,7 @@ static void gpu_viewport_buffers_free(FramebufferList *fbl, int fbl_len, Texture
static void gpu_viewport_storage_free(StorageList *stl, int stl_len);
static void gpu_viewport_passes_free(PassList *psl, int psl_len);
static void gpu_viewport_texture_pool_free(GPUViewport *viewport);
+static void gpu_viewport_default_fb_create(GPUViewport *viewport);
void GPU_viewport_tag_update(GPUViewport *viewport)
{
@@ -125,9 +125,33 @@ GPUViewport *GPU_viewport_create(void)
GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs)
{
GPUViewport *viewport = GPU_viewport_create();
- GPU_offscreen_viewport_data_get(ofs, &viewport->fbl->default_fb, &viewport->txl->color, &viewport->txl->depth);
+ GPUTexture *color, *depth;
+ GPUFrameBuffer *fb;
viewport->size[0] = GPU_offscreen_width(ofs);
viewport->size[1] = GPU_offscreen_height(ofs);
+
+ GPU_offscreen_viewport_data_get(ofs, &fb, &color, &depth);
+
+ if (GPU_texture_samples(color)) {
+ viewport->txl->multisample_color = color;
+ viewport->txl->multisample_depth = depth;
+ viewport->fbl->multisample_fb = fb;
+ gpu_viewport_default_fb_create(viewport);
+ }
+ else {
+ viewport->fbl->default_fb = fb;
+ viewport->txl->color = color;
+ viewport->txl->depth = depth;
+ GPU_framebuffer_ensure_config(&viewport->fbl->color_only_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(viewport->txl->color)
+ });
+ GPU_framebuffer_ensure_config(&viewport->fbl->depth_only_fb, {
+ GPU_ATTACHMENT_TEXTURE(viewport->txl->depth),
+ GPU_ATTACHMENT_NONE
+ });
+ }
+
return viewport;
}
/**
@@ -135,9 +159,22 @@ GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs)
*/
void GPU_viewport_clear_from_offscreen(GPUViewport *viewport)
{
- viewport->fbl->default_fb = NULL;
- viewport->txl->color = NULL;
- viewport->txl->depth = NULL;
+ DefaultFramebufferList *dfbl = viewport->fbl;
+ DefaultTextureList *dtxl = viewport->txl;
+
+ if (dfbl->multisample_fb) {
+ /* GPUViewport expect the final result to be in default_fb but
+ * GPUOffscreen wants it in its multisample_fb, so we sync it back. */
+ GPU_framebuffer_blit(dfbl->default_fb, 0, dfbl->multisample_fb, 0, GPU_COLOR_BIT | GPU_DEPTH_BIT);
+ dfbl->multisample_fb = NULL;
+ dtxl->multisample_color = NULL;
+ dtxl->multisample_depth = NULL;
+ }
+ else {
+ viewport->fbl->default_fb = NULL;
+ dtxl->color = NULL;
+ dtxl->depth = NULL;
+ }
}
void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type)
@@ -243,6 +280,11 @@ void GPU_viewport_size_set(GPUViewport *viewport, const int size[2])
viewport->size[1] = size[1];
}
+double *GPU_viewport_cache_time_get(GPUViewport *viewport)
+{
+ return &viewport->cache_time;
+}
+
/**
* Try to find a texture coresponding to params into the texture pool.
* If no texture was found, create one and add it to the pool.
@@ -252,9 +294,9 @@ GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine,
GPUTexture *tex;
for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex->next) {
- if ((GPU_texture_width(tmp_tex->texture) == width) &&
- (GPU_texture_height(tmp_tex->texture) == height) &&
- (GPU_texture_format(tmp_tex->texture) == format))
+ if ((GPU_texture_format(tmp_tex->texture) == format) &&
+ (GPU_texture_width(tmp_tex->texture) == width) &&
+ (GPU_texture_height(tmp_tex->texture) == height))
{
/* Search if the engine is not already using this texture */
for (int i = 0; i < MAX_ENGINE_BUFFER_SHARING; ++i) {
@@ -271,11 +313,16 @@ GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine,
}
tex = GPU_texture_create_2D_custom(width, height, channels, format, NULL, NULL);
+ GPU_texture_bind(tex, 0);
+ /* Doing filtering for depth does not make sense when not doing shadow mapping,
+ * and enabling texture filtering on integer texture make them unreadable. */
+ bool do_filter = !GPU_texture_depth(tex) && !GPU_texture_integer(tex);
+ GPU_texture_filter_mode(tex, do_filter);
+ GPU_texture_unbind(tex);
ViewportTempTexture *tmp_tex = MEM_callocN(sizeof(ViewportTempTexture), "ViewportTempTexture");
tmp_tex->texture = tex;
tmp_tex->user[0] = engine;
-
BLI_addtail(&viewport->tex_pool, tmp_tex);
return tex;
@@ -335,16 +382,94 @@ void GPU_viewport_cache_release(GPUViewport *viewport)
}
}
-void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
+static void gpu_viewport_default_fb_create(GPUViewport *viewport)
+{
+ DefaultFramebufferList *dfbl = viewport->fbl;
+ DefaultTextureList *dtxl = viewport->txl;
+ int *size = viewport->size;
+ bool ok = true;
+
+ dtxl->color = GPU_texture_create_2D(size[0], size[1], NULL, NULL);
+ dtxl->depth = GPU_texture_create_depth_with_stencil(size[0], size[1], NULL);
+
+ if (!(dtxl->depth && dtxl->color)) {
+ ok = false;
+ goto cleanup;
+ }
+
+ GPU_framebuffer_ensure_config(&dfbl->default_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(dtxl->color)
+ });
+
+ GPU_framebuffer_ensure_config(&dfbl->depth_only_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_NONE
+ });
+
+ GPU_framebuffer_ensure_config(&dfbl->color_only_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(dtxl->color)
+ });
+
+ ok = ok && GPU_framebuffer_check_valid(dfbl->default_fb, NULL);
+ ok = ok && GPU_framebuffer_check_valid(dfbl->color_only_fb, NULL);
+ ok = ok && GPU_framebuffer_check_valid(dfbl->depth_only_fb, NULL);
+
+cleanup:
+ if (!ok) {
+ GPU_viewport_free(viewport);
+ DRW_opengl_context_disable();
+ return;
+ }
+
+ GPU_framebuffer_restore();
+}
+
+static void gpu_viewport_default_multisample_fb_create(GPUViewport *viewport)
{
DefaultFramebufferList *dfbl = viewport->fbl;
DefaultTextureList *dtxl = viewport->txl;
+ int *size = viewport->size;
+ int samples = viewport->samples;
+ bool ok = true;
+
+ dtxl->multisample_color = GPU_texture_create_2D_multisample(size[0], size[1], NULL, samples, NULL);
+ dtxl->multisample_depth = GPU_texture_create_depth_with_stencil_multisample(size[0], size[1], samples, NULL);
+
+ if (!(dtxl->multisample_depth && dtxl->multisample_color)) {
+ ok = false;
+ goto cleanup;
+ }
+
+ GPU_framebuffer_ensure_config(&dfbl->multisample_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->multisample_depth),
+ GPU_ATTACHMENT_TEXTURE(dtxl->multisample_color)
+ });
+
+ ok = ok && GPU_framebuffer_check_valid(dfbl->multisample_fb, NULL);
+
+cleanup:
+ if (!ok) {
+ GPU_viewport_free(viewport);
+ DRW_opengl_context_disable();
+ return;
+ }
+
+ GPU_framebuffer_restore();
+}
+
+void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
+{
+ DefaultFramebufferList *dfbl = viewport->fbl;
int fbl_len, txl_len;
/* add one pixel because of scissor test */
int rect_w = BLI_rcti_size_x(rect) + 1;
int rect_h = BLI_rcti_size_y(rect) + 1;
+ DRW_opengl_context_enable();
+
if (dfbl->default_fb) {
if (rect_w != viewport->size[0] || rect_h != viewport->size[1] || U.ogl_multisamples != viewport->samples) {
gpu_viewport_buffers_free(
@@ -361,121 +486,31 @@ void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
}
}
+ viewport->size[0] = rect_w;
+ viewport->size[1] = rect_h;
+ viewport->samples = U.ogl_multisamples;
+
gpu_viewport_texture_pool_clear_users(viewport);
/* Multisample Buffer */
- if (U.ogl_multisamples > 0) {
+ if (viewport->samples > 0) {
if (!dfbl->default_fb) {
- bool ok = true;
- viewport->samples = U.ogl_multisamples;
-
- dfbl->multisample_fb = GPU_framebuffer_create();
- if (!dfbl->multisample_fb) {
- ok = false;
- goto cleanup_multisample;
- }
-
- /* Color */
- dtxl->multisample_color = GPU_texture_create_2D_multisample(rect_w, rect_h, NULL, U.ogl_multisamples, NULL);
- if (!dtxl->multisample_color) {
- ok = false;
- goto cleanup_multisample;
- }
-
- if (!GPU_framebuffer_texture_attach(dfbl->multisample_fb, dtxl->multisample_color, 0, 0)) {
- ok = false;
- goto cleanup_multisample;
- }
-
- /* Depth */
- dtxl->multisample_depth = GPU_texture_create_depth_with_stencil_multisample(rect_w, rect_h,
- U.ogl_multisamples, NULL);
-
- if (!dtxl->multisample_depth) {
- ok = false;
- goto cleanup_multisample;
- }
-
- if (!GPU_framebuffer_texture_attach(dfbl->multisample_fb, dtxl->multisample_depth, 0, 0)) {
- ok = false;
- goto cleanup_multisample;
- }
- else if (!GPU_framebuffer_check_valid(dfbl->multisample_fb, NULL)) {
- ok = false;
- goto cleanup_multisample;
- }
-
-cleanup_multisample:
- if (!ok) {
- GPU_viewport_free(viewport);
- MEM_freeN(viewport);
- return;
- }
+ gpu_viewport_default_multisample_fb_create(viewport);
}
}
if (!dfbl->default_fb) {
- bool ok = true;
- viewport->size[0] = rect_w;
- viewport->size[1] = rect_h;
-
- dfbl->default_fb = GPU_framebuffer_create();
- if (!dfbl->default_fb) {
- ok = false;
- goto cleanup;
- }
-
- /* Color */
- dtxl->color = GPU_texture_create_2D(rect_w, rect_h, NULL, NULL);
- if (!dtxl->color) {
- ok = false;
- goto cleanup;
- }
-
- if (!GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->color, 0, 0)) {
- ok = false;
- goto cleanup;
- }
-
- /* Depth */
- dtxl->depth = GPU_texture_create_depth_with_stencil(rect_w, rect_h, NULL);
-
- if (dtxl->depth) {
- /* Define texture parameters */
- GPU_texture_bind(dtxl->depth, 0);
- GPU_texture_compare_mode(dtxl->depth, false);
- GPU_texture_filter_mode(dtxl->depth, true);
- GPU_texture_unbind(dtxl->depth);
- }
- else {
- ok = false;
- goto cleanup;
- }
-
- if (!GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0)) {
- ok = false;
- goto cleanup;
- }
- else if (!GPU_framebuffer_check_valid(dfbl->default_fb, NULL)) {
- ok = false;
- goto cleanup;
- }
-
-cleanup:
- if (!ok) {
- GPU_viewport_free(viewport);
- MEM_freeN(viewport);
- return;
- }
-
- GPU_framebuffer_restore();
+ gpu_viewport_default_fb_create(viewport);
}
-
- GPU_framebuffer_slots_bind(dfbl->default_fb, 0);
}
-static void draw_ofs_to_screen(GPUViewport *viewport)
+void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect)
{
+ DefaultFramebufferList *dfbl = viewport->fbl;
+
+ if (dfbl->default_fb == NULL)
+ return;
+
DefaultTextureList *dtxl = viewport->txl;
GPUTexture *color = dtxl->color;
@@ -483,50 +518,31 @@ static void draw_ofs_to_screen(GPUViewport *viewport)
const float w = (float)GPU_texture_width(color);
const float h = (float)GPU_texture_height(color);
- Gwn_VertFormat *format = immVertexFormat();
- unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA);
- GPU_texture_bind(color, 0);
-
- immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
-
- immBegin(GWN_PRIM_TRI_STRIP, 4);
+ BLI_assert(w == BLI_rcti_size_x(rect) + 1);
+ BLI_assert(h == BLI_rcti_size_y(rect) + 1);
- immAttrib2f(texcoord, 0.0f, 0.0f);
- immVertex2f(pos, 0.0f, 0.0f);
+ float x1 = rect->xmin;
+ float x2 = rect->xmin + w;
+ float y1 = rect->ymin;
+ float y2 = rect->ymin + h;
- immAttrib2f(texcoord, 1.0f, 0.0f);
- immVertex2f(pos, w, 0.0f);
+ GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
+ GPU_shader_bind(shader);
- immAttrib2f(texcoord, 0.0f, 1.0f);
- immVertex2f(pos, 0.0f, h);
-
- immAttrib2f(texcoord, 1.0f, 1.0f);
- immVertex2f(pos, w, h);
+ GPU_texture_bind(color, 0);
+ glUniform1i(GPU_shader_get_uniform(shader, "image"), 0);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), 0.0f, 0.0f, 1.0f, 1.0f);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), x1, y1, x2, y2);
+ glUniform4f(GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_COLOR), 1.0f, 1.0f, 1.0f, 1.0f);
- immEnd();
+ GWN_draw_primitive(GWN_PRIM_TRI_STRIP, 4);
GPU_texture_unbind(color);
-
- immUnbindProgram();
}
-void GPU_viewport_unbind(GPUViewport *viewport)
+void GPU_viewport_unbind(GPUViewport *UNUSED(viewport))
{
- DefaultFramebufferList *dfbl = viewport->fbl;
-
- if (dfbl->default_fb) {
- GPU_framebuffer_texture_unbind(NULL, NULL);
- GPU_framebuffer_restore();
-
- glEnable(GL_SCISSOR_TEST);
- glDisable(GL_DEPTH_TEST);
-
- /* This might be bandwidth limiting */
- draw_ofs_to_screen(viewport);
- }
+ DRW_opengl_context_disable();
}
static void gpu_viewport_buffers_free(
@@ -571,6 +587,7 @@ static void gpu_viewport_passes_free(PassList *psl, int psl_len)
}
}
+/* Must be executed inside Drawmanager Opengl Context. */
void GPU_viewport_free(GPUViewport *viewport)
{
gpu_viewport_engines_data_free(viewport);
@@ -587,8 +604,8 @@ void GPU_viewport_free(GPUViewport *viewport)
if (viewport->vmempool.calls != NULL) {
BLI_mempool_destroy(viewport->vmempool.calls);
}
- if (viewport->vmempool.calls_generate != NULL) {
- BLI_mempool_destroy(viewport->vmempool.calls_generate);
+ if (viewport->vmempool.states != NULL) {
+ BLI_mempool_destroy(viewport->vmempool.states);
}
if (viewport->vmempool.shgroups != NULL) {
BLI_mempool_destroy(viewport->vmempool.shgroups);
@@ -603,84 +620,5 @@ void GPU_viewport_free(GPUViewport *viewport)
DRW_instance_data_list_free(viewport->idatalist);
MEM_freeN(viewport->idatalist);
- GPU_viewport_debug_depth_free(viewport);
-}
-
-/****************** debug ********************/
-
-bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256])
-{
- viewport->debug_depth = GPU_texture_create_2D_custom(width, height, 4, GPU_RGBA16F, NULL, err_out);
- return (viewport->debug_depth != NULL);
-}
-
-void GPU_viewport_debug_depth_free(GPUViewport *viewport)
-{
- if (viewport->debug_depth != NULL) {
- MEM_freeN(viewport->debug_depth);
- viewport->debug_depth = NULL;
- }
-}
-
-void GPU_viewport_debug_depth_store(GPUViewport *viewport, const int x, const int y)
-{
- const int w = GPU_texture_width(viewport->debug_depth);
- const int h = GPU_texture_height(viewport->debug_depth);
-
- GPU_texture_bind(viewport->debug_depth, 0);
- glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, x, y, w, h, 0);
- GPU_texture_unbind(viewport->debug_depth);
-}
-
-void GPU_viewport_debug_depth_draw(GPUViewport *viewport, const float znear, const float zfar)
-{
- const float w = (float)GPU_texture_width(viewport->debug_depth);
- const float h = (float)GPU_texture_height(viewport->debug_depth);
-
- Gwn_VertFormat *format = immVertexFormat();
- unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_DEPTH);
-
- GPU_texture_bind(viewport->debug_depth, 0);
-
- immUniform1f("znear", znear);
- immUniform1f("zfar", zfar);
- immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
-
- immBegin(GWN_PRIM_TRI_STRIP, 4);
-
- immAttrib2f(texcoord, 0.0f, 0.0f);
- immVertex2f(pos, 0.0f, 0.0f);
-
- immAttrib2f(texcoord, 1.0f, 0.0f);
- immVertex2f(pos, w, 0.0f);
-
- immAttrib2f(texcoord, 0.0f, 1.0f);
- immVertex2f(pos, 0.0f, h);
-
- immAttrib2f(texcoord, 1.0f, 1.0f);
- immVertex2f(pos, w, h);
-
- immEnd();
-
- GPU_texture_unbind(viewport->debug_depth);
-
- immUnbindProgram();
-}
-
-int GPU_viewport_debug_depth_width(const GPUViewport *viewport)
-{
- return GPU_texture_width(viewport->debug_depth);
-}
-
-int GPU_viewport_debug_depth_height(const GPUViewport *viewport)
-{
- return GPU_texture_height(viewport->debug_depth);
-}
-
-bool GPU_viewport_debug_depth_is_valid(GPUViewport *viewport)
-{
- return viewport->debug_depth != NULL;
+ MEM_freeN(viewport);
}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl
new file mode 100644
index 00000000000..9fdf8ececc5
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl
@@ -0,0 +1,48 @@
+/**
+ * Simple shader that just draw multiple icons at the specified locations
+ * does not need any vertex input (producing less call to immBegin/End)
+ **/
+
+/* Same as ICON_DRAW_CACHE_SIZE */
+#define MAX_CALLS 16
+
+uniform vec4 calls_data[MAX_CALLS * 3];
+
+out vec2 texCoord_interp;
+flat out vec4 finalColor;
+
+void main()
+{
+ /* Rendering 2 triangle per icon. */
+ int i = gl_VertexID / 6;
+ int v = gl_VertexID % 6;
+
+ vec4 pos = calls_data[i*3];
+ vec4 tex = calls_data[i*3+1];
+ finalColor = calls_data[i*3+2];
+
+ /* TODO Remove this */
+ if (v == 2) v = 4;
+ else if (v == 3) v = 0;
+ else if (v == 5) v = 2;
+
+ if (v == 0) {
+ pos.xy = pos.xw;
+ tex.xy = tex.xw;
+ }
+ else if (v == 1) {
+ pos.xy = pos.xz;
+ tex.xy = tex.xz;
+ }
+ else if (v == 2) {
+ pos.xy = pos.yw;
+ tex.xy = tex.yw;
+ }
+ else {
+ pos.xy = pos.yz;
+ tex.xy = tex.yz;
+ }
+
+ gl_Position = vec4(pos.xy, 0.0f, 1.0f);
+ texCoord_interp = tex.xy;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl
new file mode 100644
index 00000000000..118f4e3b187
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl
@@ -0,0 +1,35 @@
+/**
+ * Simple shader that just draw one icon at the specified location
+ * does not need any vertex input (producing less call to immBegin/End)
+ **/
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec4 rect_icon;
+uniform vec4 rect_geom;
+
+out vec2 texCoord_interp;
+
+void main()
+{
+ vec2 uv;
+ vec2 co;
+ if (gl_VertexID == 0) {
+ co = rect_geom.xw;
+ uv = rect_icon.xw;
+ }
+ else if (gl_VertexID == 1) {
+ co = rect_geom.xy;
+ uv = rect_icon.xy;
+ }
+ else if (gl_VertexID == 2) {
+ co = rect_geom.zw;
+ uv = rect_icon.zw;
+ }
+ else {
+ co = rect_geom.zy;
+ uv = rect_icon.zy;
+ }
+
+ gl_Position = ModelViewProjectionMatrix * vec4(co, 0.0f, 1.0f);
+ texCoord_interp = uv;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_frag.glsl
new file mode 100644
index 00000000000..8dda575107a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_frag.glsl
@@ -0,0 +1,10 @@
+
+in float colorGradient;
+in vec4 finalColor;
+
+out vec4 fragColor;
+
+void main() {
+ fragColor = finalColor;
+ fragColor.a *= smoothstep(1.0, 0.1, abs(colorGradient));
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl
new file mode 100644
index 00000000000..4c295fcd72a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl
@@ -0,0 +1,107 @@
+/**
+ * 2D Quadratic Bezier thick line drawing
+ **/
+
+#define MID_VERTEX 57
+
+/* u is position along the curve, defining the tangent space.
+ * v is "signed" distance (compressed to [0..1] range) from the pos in expand direction */
+in vec2 uv;
+in vec2 pos; /* verts position in the curve tangent space */
+in vec2 expand;
+
+#ifdef USE_INSTANCE
+/* Instance attrib */
+in vec2 P0;
+in vec2 P1;
+in vec2 P2;
+in vec2 P3;
+in ivec4 colid_doarrow;
+
+uniform vec4 colors[6];
+
+#define colStart colors[colid_doarrow[0]]
+#define colEnd colors[colid_doarrow[1]]
+#define colShadow colors[colid_doarrow[2]]
+#define doArrow (colid_doarrow[3] != 0)
+
+#else
+/* Single curve drawcall, use uniform. */
+uniform vec2 bezierPts[4];
+
+#define P0 bezierPts[0]
+#define P1 bezierPts[1]
+#define P2 bezierPts[2]
+#define P3 bezierPts[3]
+
+uniform vec4 colors[3];
+uniform bool doArrow;
+
+#define colShadow colors[0]
+#define colStart colors[1]
+#define colEnd colors[2]
+
+#endif
+
+uniform float expandSize;
+uniform float arrowSize;
+uniform mat4 ModelViewProjectionMatrix;
+
+out float colorGradient;
+out vec4 finalColor;
+
+void main(void)
+{
+ float t = uv.x;
+ float t2 = t * t;
+ float t2_3 = 3.0 * t2;
+ float one_minus_t = 1.0 - t;
+ float one_minus_t2 = one_minus_t * one_minus_t;
+ float one_minus_t2_3 = 3.0 * one_minus_t2;
+
+ vec2 point = (P0 * one_minus_t2 * one_minus_t +
+ P1 * one_minus_t2_3 * t +
+ P2 * t2_3 * one_minus_t +
+ P3 * t2 * t);
+
+ vec2 tangent = ((P1 - P0) * one_minus_t2_3 +
+ (P2 - P1) * 6.0 * (t - t2) +
+ (P3 - P2) * t2_3);
+
+ /* tangent space at t */
+ tangent = normalize(tangent);
+ vec2 normal = tangent.yx * vec2(-1.0, 1.0);
+
+ /* Position vertex on the curve tangent space */
+ point += (pos.x * tangent + pos.y * normal) * arrowSize;
+
+ gl_Position = ModelViewProjectionMatrix * vec4(point, 0.0, 1.0);
+
+ vec2 exp_axis = expand.x * tangent + expand.y * normal;
+
+ /* rotate & scale the expand axis */
+ exp_axis = ModelViewProjectionMatrix[0].xy * exp_axis.xx +
+ ModelViewProjectionMatrix[1].xy * exp_axis.yy;
+
+
+ float expand_dist = (uv.y * 2.0 - 1.0);
+ colorGradient = expand_dist;
+
+ if (gl_VertexID < MID_VERTEX) {
+ /* Shadow pass */
+ finalColor = colShadow;
+ }
+ else {
+ /* Second pass */
+ finalColor = mix(colStart, colEnd, uv.x);
+ expand_dist *= 0.5;
+ }
+
+ /* Expand into a line */
+ gl_Position.xy += exp_axis * expandSize * expand_dist;
+
+ /* if arrow */
+ if (expand.y != 1.0 && !doArrow) {
+ gl_Position.xy *= 0.0;
+ }
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl
new file mode 100644
index 00000000000..f660cae8d12
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl
@@ -0,0 +1,35 @@
+uniform vec3 checkerColorAndSize;
+
+noperspective in vec4 finalColor;
+noperspective in float butCo;
+
+out vec4 fragColor;
+
+vec4 do_checkerboard()
+{
+ float size = checkerColorAndSize.z;
+ vec2 phase = mod(gl_FragCoord.xy, size * 2.0);
+
+ if ((phase.x > size && phase.y < size) ||
+ (phase.x < size && phase.y > size))
+ {
+ return vec4(checkerColorAndSize.xxx, 1.0);
+ }
+ else {
+ return vec4(checkerColorAndSize.yyy, 1.0);
+ }
+}
+
+void main()
+{
+ fragColor = finalColor;
+
+ if (butCo > 0.5) {
+ vec4 checker = do_checkerboard();
+ fragColor = mix(checker, fragColor, fragColor.a);
+ }
+
+ if (butCo > 0.0) {
+ fragColor.a = 1.0;
+ }
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
new file mode 100644
index 00000000000..0c351a3bce4
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
@@ -0,0 +1,186 @@
+#define BIT_RANGE(x) uint((1 << x) - 1)
+
+/* 2 bits for corner */
+/* Attention! Not the same order as in UI_interface.h!
+ * Ordered by drawing order. */
+#define BOTTOM_LEFT 0u
+#define BOTTOM_RIGHT 1u
+#define TOP_RIGHT 2u
+#define TOP_LEFT 3u
+#define CNR_FLAG_RANGE BIT_RANGE(2)
+
+/* 4bits for corner id */
+#define CORNER_VEC_OFS 2u
+#define CORNER_VEC_RANGE BIT_RANGE(4)
+const vec2 cornervec[36] = vec2[36](
+ vec2(0.0, 1.0), vec2(0.02, 0.805), vec2(0.067, 0.617), vec2(0.169, 0.45), vec2(0.293, 0.293), vec2(0.45, 0.169), vec2(0.617, 0.076), vec2(0.805, 0.02), vec2(1.0, 0.0),
+ vec2(-1.0, 0.0), vec2(-0.805, 0.02), vec2(-0.617, 0.067), vec2(-0.45, 0.169), vec2(-0.293, 0.293), vec2(-0.169, 0.45), vec2(-0.076, 0.617), vec2(-0.02, 0.805), vec2(0.0, 1.0),
+ vec2(0.0, -1.0), vec2(-0.02, -0.805), vec2(-0.067, -0.617), vec2(-0.169, -0.45), vec2(-0.293, -0.293), vec2(-0.45, -0.169), vec2(-0.617, -0.076), vec2(-0.805, -0.02), vec2(-1.0, 0.0),
+ vec2(1.0, 0.0), vec2(0.805, -0.02), vec2(0.617, -0.067), vec2(0.45, -0.169), vec2(0.293, -0.293), vec2(0.169, -0.45), vec2(0.076, -0.617), vec2(0.02, -0.805), vec2(0.0, -1.0)
+);
+
+/* 4bits for jitter id */
+#define JIT_OFS 6u
+#define JIT_RANGE BIT_RANGE(4)
+const vec2 jit[9] = vec2[9](
+ vec2( 0.468813, -0.481430), vec2(-0.155755, -0.352820),
+ vec2( 0.219306, -0.238501), vec2(-0.393286, -0.110949),
+ vec2(-0.024699, 0.013908), vec2( 0.343805, 0.147431),
+ vec2(-0.272855, 0.269918), vec2( 0.095909, 0.388710),
+ vec2( 0.0, 0.0)
+);
+
+/* 2bits for other flags */
+#define INNER_FLAG uint(1 << 10) /* is inner vert */
+#define EMBOSS_FLAG uint(1 << 11) /* is emboss vert */
+
+/* 2bits for color */
+#define COLOR_OFS 12u
+#define COLOR_RANGE BIT_RANGE(2)
+#define COLOR_INNER 0u
+#define COLOR_EDGE 1u
+#define COLOR_EMBOSS 2u
+
+/* 2bits for trias type */
+#define TRIA_FLAG uint(1 << 14) /* is tria vert */
+#define TRIA_FIRST INNER_FLAG /* is first tria (reuse INNER_FLAG) */
+
+/* We can reuse the CORNER_* bits for tria */
+#define TRIA_VEC_RANGE BIT_RANGE(6)
+const vec2 triavec[34] = vec2[34](
+ /* horizontal tria */
+ vec2(-0.352077, 0.532607), vec2(-0.352077, -0.549313), vec2( 0.330000, -0.008353),
+ vec2( 0.352077, 0.532607), vec2( 0.352077, -0.549313), vec2(-0.330000, -0.008353),
+ /* circle tria (triangle strip) */
+ vec2(0.000000, 1.000000),
+ vec2(0.382684, 0.923879), vec2(-0.382683, 0.923880),
+ vec2(0.707107, 0.707107), vec2(-0.707107, 0.707107),
+ vec2(0.923879, 0.382684), vec2(-0.923879, 0.382684),
+ vec2(1.000000, 0.000000), vec2(-1.000000, 0.000000),
+ vec2(0.923879, -0.382684), vec2(-0.923879, -0.382684),
+ vec2(0.707107, -0.707107), vec2(-0.707107, -0.707107),
+ vec2(0.382684, -0.923879), vec2(-0.382683, -0.923880),
+ vec2(0.000000, -1.000000),
+ /* menu arrow */
+ vec2(-0.33, 0.16), vec2(0.33, 0.16), vec2(0.0, 0.82),
+ vec2(0.0, -0.82), vec2(-0.33, -0.16), vec2(0.33, -0.16),
+ /* check mark */
+ vec2(-0.578579, 0.253369), vec2(-0.392773, 0.412794), vec2(-0.004241, -0.328551),
+ vec2(-0.003001, 0.034320), vec2(1.055313, 0.864744), vec2(0.866408, 1.026895)
+);
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#ifdef USE_INSTANCE
+#define MAX_INSTANCE 6
+uniform vec4 parameters[11 * MAX_INSTANCE];
+#else
+uniform vec4 parameters[11];
+#endif
+
+/* gl_InstanceID is 0 if not drawing instances. */
+#define recti parameters[gl_InstanceID * 11 + 0]
+#define rect parameters[gl_InstanceID * 11 + 1]
+#define radsi parameters[gl_InstanceID * 11 + 2].x
+#define rads parameters[gl_InstanceID * 11 + 2].y
+#define faci parameters[gl_InstanceID * 11 + 2].zw
+#define roundCorners parameters[gl_InstanceID * 11 + 3]
+#define colorInner1 parameters[gl_InstanceID * 11 + 4]
+#define colorInner2 parameters[gl_InstanceID * 11 + 5]
+#define colorEdge parameters[gl_InstanceID * 11 + 6]
+#define colorEmboss parameters[gl_InstanceID * 11 + 7]
+#define colorTria parameters[gl_InstanceID * 11 + 8]
+#define tria1Center parameters[gl_InstanceID * 11 + 9].xy
+#define tria2Center parameters[gl_InstanceID * 11 + 9].zw
+#define tria1Size parameters[gl_InstanceID * 11 + 10].x
+#define tria2Size parameters[gl_InstanceID * 11 + 10].y
+#define shadeDir parameters[gl_InstanceID * 11 + 10].z
+#define doAlphaCheck parameters[gl_InstanceID * 11 + 10].w
+
+in uint vflag;
+
+noperspective out vec4 finalColor;
+noperspective out float butCo;
+
+vec2 do_widget(void)
+{
+ uint cflag = vflag & CNR_FLAG_RANGE;
+ uint vofs = (vflag >> CORNER_VEC_OFS) & CORNER_VEC_RANGE;
+
+ vec2 v = cornervec[cflag * 9u + vofs];
+
+ bool is_inner = (vflag & INNER_FLAG) != 0u;
+
+ /* Scale by corner radius */
+ v *= roundCorners[cflag] * ((is_inner) ? radsi : rads);
+
+ /* Position to corner */
+ vec4 rct = (is_inner) ? recti : rect;
+ if (cflag == BOTTOM_LEFT)
+ v += rct.xz;
+ else if (cflag == BOTTOM_RIGHT)
+ v += rct.yz;
+ else if (cflag == TOP_RIGHT)
+ v += rct.yw;
+ else /* (cflag == TOP_LEFT) */
+ v += rct.xw;
+
+ /* compute uv and color gradient */
+ uint color_id = (vflag >> COLOR_OFS) & COLOR_RANGE;
+ if (color_id == COLOR_INNER) {
+ vec2 uv = faci * (v - recti.xz);
+ float fac = clamp((shadeDir > 0.0) ? uv.y : uv.x, 0.0, 1.0);
+ if (doAlphaCheck != 0.0) {
+ finalColor = colorInner1;
+ butCo = uv.x;
+ }
+ else {
+ finalColor = mix(colorInner2, colorInner1, fac);
+ butCo = -1.0;
+ }
+ }
+ else if (color_id == COLOR_EDGE) {
+ finalColor = colorEdge;
+ butCo = -1.0;
+ }
+ else /* (color_id == COLOR_EMBOSS) */ {
+ finalColor = colorEmboss;
+ butCo = -1.0;
+ }
+
+ bool is_emboss = (vflag & EMBOSS_FLAG) != 0u;
+ v.y -= (is_emboss) ? 1.0f : 0.0;
+
+ return v;
+}
+
+vec2 do_tria()
+{
+ uint vofs = vflag & TRIA_VEC_RANGE;
+
+ vec2 v = triavec[vofs];
+
+ finalColor = colorTria;
+ butCo = -1.0;
+
+ bool is_tria_first = (vflag & TRIA_FIRST) != 0u;
+
+ if (is_tria_first)
+ v = v * tria1Size + tria1Center;
+ else
+ v = v * tria2Size + tria2Center;
+
+ return v;
+}
+
+void main()
+{
+ bool is_tria = (vflag & TRIA_FLAG) != 0u;
+
+ vec2 v = (is_tria) ? do_tria() : do_widget();
+
+ /* Antialiasing offset */
+ v += jit[(vflag >> JIT_OFS) & JIT_RANGE];
+
+ gl_Position = ModelViewProjectionMatrix * vec4(v, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl
new file mode 100644
index 00000000000..7587b2fc18a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl
@@ -0,0 +1,13 @@
+
+in float shadowFalloff;
+
+out vec4 fragColor;
+
+uniform float alpha;
+
+void main()
+{
+ fragColor = vec4(0.0);
+ /* Manual curve fit of the falloff curve of previous drawing method. */
+ fragColor.a = alpha * (shadowFalloff * shadowFalloff * 0.722 + shadowFalloff * 0.277);
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl
new file mode 100644
index 00000000000..2f5353a7c86
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl
@@ -0,0 +1,64 @@
+#define BIT_RANGE(x) uint((1 << x) - 1)
+
+/* 2 bits for corner */
+/* Attention! Not the same order as in UI_interface.h!
+ * Ordered by drawing order. */
+#define BOTTOM_LEFT 0u
+#define BOTTOM_RIGHT 1u
+#define TOP_RIGHT 2u
+#define TOP_LEFT 3u
+#define CNR_FLAG_RANGE BIT_RANGE(2)
+
+/* 4bits for corner id */
+#define CORNER_VEC_OFS 2u
+#define CORNER_VEC_RANGE BIT_RANGE(4)
+const vec2 cornervec[36] = vec2[36](
+ vec2(0.0, 1.0), vec2(0.02, 0.805), vec2(0.067, 0.617), vec2(0.169, 0.45), vec2(0.293, 0.293), vec2(0.45, 0.169), vec2(0.617, 0.076), vec2(0.805, 0.02), vec2(1.0, 0.0),
+ vec2(-1.0, 0.0), vec2(-0.805, 0.02), vec2(-0.617, 0.067), vec2(-0.45, 0.169), vec2(-0.293, 0.293), vec2(-0.169, 0.45), vec2(-0.076, 0.617), vec2(-0.02, 0.805), vec2(0.0, 1.0),
+ vec2(0.0, -1.0), vec2(-0.02, -0.805), vec2(-0.067, -0.617), vec2(-0.169, -0.45), vec2(-0.293, -0.293), vec2(-0.45, -0.169), vec2(-0.617, -0.076), vec2(-0.805, -0.02), vec2(-1.0, 0.0),
+ vec2(1.0, 0.0), vec2(0.805, -0.02), vec2(0.617, -0.067), vec2(0.45, -0.169), vec2(0.293, -0.293), vec2(0.169, -0.45), vec2(0.076, -0.617), vec2(0.02, -0.805), vec2(0.0, -1.0)
+);
+
+#define INNER_FLAG uint(1 << 10) /* is inner vert */
+
+uniform mat4 ModelViewProjectionMatrix;
+
+uniform vec4 parameters[4];
+/* radi and rad per corner */
+#define recti parameters[0]
+#define rect parameters[1]
+#define radsi parameters[2].x
+#define rads parameters[2].y
+#define roundCorners parameters[3]
+
+in uint vflag;
+
+out float shadowFalloff;
+
+void main()
+{
+ uint cflag = vflag & CNR_FLAG_RANGE;
+ uint vofs = (vflag >> CORNER_VEC_OFS) & CORNER_VEC_RANGE;
+
+ vec2 v = cornervec[cflag * 9u + vofs];
+
+ bool is_inner = (vflag & INNER_FLAG) != 0u;
+
+ shadowFalloff = (is_inner) ? 1.0 : 0.0;
+
+ /* Scale by corner radius */
+ v *= roundCorners[cflag] * ((is_inner) ? radsi : rads);
+
+ /* Position to corner */
+ vec4 rct = (is_inner) ? recti : rect;
+ if (cflag == BOTTOM_LEFT)
+ v += rct.xz;
+ else if (cflag == BOTTOM_RIGHT)
+ v += rct.yz;
+ else if (cflag == TOP_RIGHT)
+ v += rct.yw;
+ else /* (cflag == TOP_LEFT) */
+ v += rct.xw;
+
+ gl_Position = ModelViewProjectionMatrix * vec4(v, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl
new file mode 100644
index 00000000000..10f4dfd5a87
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl
@@ -0,0 +1,12 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform sampler2D image;
+
+void main()
+{
+ float depth = texture(image, texCoord_interp).r;
+ fragColor = vec4(depth);
+ gl_FragDepth = depth;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_frag.glsl
index 7d9ce9d2003..6eeab8ca7e8 100644
--- a/source/blender/gpu/shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_image_frag.glsl
@@ -2,11 +2,9 @@
in vec2 texCoord_interp;
out vec4 fragColor;
-uniform float alpha;
-uniform sampler2DRect image;
+uniform sampler2D image;
void main()
{
fragColor = texture(image, texCoord_interp);
- fragColor.a *= alpha;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl
index 7f3e7df40ac..d95645f58e5 100644
--- a/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl
@@ -8,8 +8,8 @@ in vec2 texCoord_interp;
out vec4 fragColor;
uniform int interlace_id;
-uniform sampler2DRect image_a;
-uniform sampler2DRect image_b;
+uniform sampler2D image_a;
+uniform sampler2D image_b;
bool interlace()
{
diff --git a/source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl
new file mode 100644
index 00000000000..37686092700
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl
@@ -0,0 +1,11 @@
+
+in vec2 texCoord_interp;
+flat in vec4 finalColor;
+out vec4 fragColor;
+
+uniform sampler2D image;
+
+void main()
+{
+ fragColor = texture(image, texCoord_interp) * finalColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_mball_helpers_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_mball_handles_vert.glsl
index 819199c26c7..819199c26c7 100644
--- a/source/blender/gpu/shaders/gpu_shader_instance_mball_helpers_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_instance_mball_handles_vert.glsl
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 780f4f59fb9..d3bc1f0ef8e 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1,16 +1,9 @@
-uniform mat4 ModelViewMatrix;
-#ifndef EEVEE_ENGINE
-uniform mat4 ProjectionMatrix;
-uniform mat4 ViewMatrixInverse;
-uniform mat4 ViewMatrix;
-#endif
uniform mat4 ModelMatrix;
uniform mat4 ModelMatrixInverse;
+uniform mat4 ModelViewMatrix;
uniform mat4 ModelViewMatrixInverse;
-uniform mat4 ProjectionMatrixInverse;
uniform mat3 NormalMatrix;
-uniform vec4 CameraTexCoFactors;
/* Old glsl mode compat. */
@@ -238,16 +231,18 @@ void geom(
}
void particle_info(
- vec4 sprops, vec3 loc, vec3 vel, vec3 avel,
- out float index, out float age, out float life_time, out vec3 location,
+ 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;
+ location = loc.xyz;
velocity = vel;
angular_velocity = avel;
}
@@ -2533,8 +2528,7 @@ uint hash(int kx, int ky, int kz)
float bits_to_01(uint bits)
{
- float x = float(bits) * (1.0 / float(0xffffffffu));
- return x;
+ return (float(bits) / 4294967295.0);
}
float cellnoise(vec3 p)
@@ -2696,7 +2690,6 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Clo
{
#ifdef EEVEE_ENGINE
vec3 out_spec, ssr_spec;
- roughness = sqrt(roughness);
eevee_closure_glossy(N, vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec);
vec3 vN = normalize(mat3(ViewMatrix) * N);
result = CLOSURE_DEFAULT;
@@ -2718,7 +2711,8 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Clo
vec3 light_specular = glLightSource[i].specular.rgb;
/* we mix in some diffuse so low roughness still shows up */
- float bsdf = 0.5 * pow(max(dot(N, H), 0.0), 1.0 / roughness);
+ float r2 = roughness * roughness;
+ float bsdf = 0.5 * pow(max(dot(N, H), 0.0), 1.0 / r2);
bsdf += 0.5 * max(dot(N, light_position), 0.0);
L += light_specular * bsdf;
}
@@ -2738,7 +2732,6 @@ void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, float ssr_i
{
#ifdef EEVEE_ENGINE
vec3 out_spec, out_refr, ssr_spec;
- roughness = sqrt(roughness);
vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb : color.rgb; /* Simulate 2 transmission event */
eevee_closure_glass(N, vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec);
out_refr *= refr_color;
@@ -2977,9 +2970,10 @@ void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Cl
#ifdef EEVEE_ENGINE
vec3 out_refr;
color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */
- roughness = sqrt(roughness);
eevee_closure_refraction(N, roughness, ior, out_refr);
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
result = CLOSURE_DEFAULT;
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
result.radiance = out_refr * color.rgb;
result.ssr_id = REFRACT_CLOSURE_FLAG;
#else
@@ -3004,7 +2998,7 @@ void node_ambient_occlusion(vec4 color, out Closure result)
/* emission */
-void node_emission(vec4 color, float strength, vec3 N, out Closure result)
+void node_emission(vec4 color, float strength, vec3 vN, out Closure result)
{
#ifndef VOLUMETRICS
color *= strength;
@@ -3012,7 +3006,7 @@ void node_emission(vec4 color, float strength, vec3 N, out Closure result)
result = CLOSURE_DEFAULT;
result.radiance = color.rgb;
result.opacity = color.a;
- result.ssr_normal = normal_encode(N, viewCameraVec);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
#else
result = Closure(color.rgb, color.a);
#endif
@@ -3072,6 +3066,86 @@ void node_volume_absorption(vec4 color, float density, out Closure result)
#endif
}
+void node_blackbody(float temperature, sampler2D spectrummap, 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, 0.0)).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,
+ sampler2D spectrummap,
+ 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 T4 = (T * T) * (T * T);
+ 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, bb);
+ emission_coeff += bb.rgb * blackbody_tint.rgb * intensity;
+ }
+ }
+
+ result = Closure(absorption_coeff, scatter_coeff, emission_coeff, anisotropy);
+#else
+ result = CLOSURE_DEFAULT;
+#endif
+}
+
/* closures */
void node_mix_shader(float fac, Closure shader1, Closure shader2, out Closure shader)
@@ -3150,7 +3224,13 @@ void node_attribute_volume_color(sampler3D tex, out vec4 outcol, out vec3 outvec
#else
vec3 cos = vec3(0.0);
#endif
- outvec = texture(tex, cos).rgb;
+
+ 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;
outcol = vec4(outvec, 1.0);
outf = dot(vec3(1.0 / 3.0), outvec);
}
@@ -3162,9 +3242,23 @@ void node_attribute_volume_flame(sampler3D tex, out vec4 outcol, out vec3 outvec
#else
vec3 cos = vec3(0.0);
#endif
- outvec = texture(tex, cos).rrr;
- outcol = vec4(outvec, 1.0);
- outf = dot(vec3(1.0 / 3.0), outvec);
+ 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(EEVEE_ENGINE) && 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)
@@ -3657,17 +3751,29 @@ float noise_perlin(float x, float y, float z)
float v = noise_fade(fy);
float w = noise_fade(fz);
- float result;
+ 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]);
- result = noise_nerp(w, noise_nerp(v, 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_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_nerp(v, 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_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))));
- return noise_scale3(result);
+ 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]);
+
+ return noise_scale3(noise_nerp(w, noise_v[0], noise_v[1]));
}
float noise(vec3 p)
@@ -4135,9 +4241,38 @@ void node_bevel(float radius, vec3 N, out vec3 result)
result = N;
}
-void node_displacement(float height, float dist, vec3 N, out vec3 result)
+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)
+{
+ 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 = height * dist * N;
+ result = (vector.xyz - vec3(midlevel)) * scale;
}
/* output */
diff --git a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
index 1319e386c65..fca39852c2a 100644
--- a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
@@ -1,12 +1,14 @@
-uniform mat4 ModelViewProjectionMatrix;
-
-in vec2 pos;
-in vec2 uvs;
out vec2 texCoord_interp;
void main()
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
- texCoord_interp = uvs;
+ const vec4 vert[3] = vec4[3](
+ vec3(-1.0, -1.0, 0.0, 0.0),
+ vec3( 3.0, -1.0, 2.0, 0.0),
+ vec3(-1.0, 3.0, 0.0, 2.0)
+ );
+
+ gl_Position = vec4(vert[gl_VertexID].xy, 0.0, 1.0);
+ texCoord_interp = vert[gl_VertexID].zw;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
index 7ff90ad4f21..fbfa4cfcc9d 100644
--- a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
@@ -1,15 +1,74 @@
flat in vec4 color_flat;
+flat in vec4 texCoord_rect;
noperspective in vec2 texCoord_interp;
out vec4 fragColor;
uniform sampler2D glyph;
+const vec2 offsets4[4] = vec2[4](
+ vec2(-0.5, 0.5), vec2( 0.5, 0.5),
+ vec2(-0.5, -0.5), vec2(-0.5, -0.5)
+);
+
+const vec2 offsets16[16] = vec2[16](
+ vec2(-1.5, 1.5), vec2(-0.5, 1.5), vec2( 0.5, 1.5), vec2( 1.5, 1.5),
+ vec2(-1.5, 0.5), vec2(-0.5, 0.5), vec2( 0.5, 0.5), vec2( 1.5, 0.5),
+ vec2(-1.5, -0.5), vec2(-0.5, -0.5), vec2( 0.5, -0.5), vec2( 1.5, -0.5),
+ vec2(-1.5, -1.5), vec2(-0.5, -1.5), vec2( 0.5, -1.5), vec2( 1.5, -1.5)
+);
+
+#define sample_glyph_offset(texco, texel, ofs) texture(glyph, texco + ofs * texel).r
+
void main()
{
// input color replaces texture color
fragColor.rgb = color_flat.rgb;
+ vec2 texel = 1.0 / vec2(textureSize(glyph, 0));
+ vec2 texco = mix(abs(texCoord_rect.xy), abs(texCoord_rect.zw), texCoord_interp);
+
// modulate input alpha & texture alpha
- fragColor.a = color_flat.a * texture(glyph, texCoord_interp).r;
+ if (texCoord_rect.x > 0) {
+ fragColor.a = texture(glyph, texco).r;
+ }
+ else {
+ fragColor.a = 0.0;
+
+ if (texCoord_rect.w > 0) {
+ /* 3x3 blur */
+ /* Manual unroll for perf. (stupid glsl compiler) */
+ fragColor.a += sample_glyph_offset(texco, texel, offsets4[0]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets4[1]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets4[2]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets4[3]);
+ fragColor.a *= (1.0 / 4.0);
+ }
+ else {
+ /* 5x5 blur */
+ /* Manual unroll for perf. (stupid glsl compiler) */
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 0]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 1]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 2]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 3]);
+
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 4]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 5]) * 2.0;
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 6]) * 2.0;
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 7]);
+
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 8]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 9]) * 2.0;
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[10]) * 2.0;
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[11]);
+
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[12]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[13]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[14]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[15]);
+ fragColor.a *= (1.0 / 20.0);
+ }
+ }
+
+ fragColor.a *= color_flat.a;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_geom.glsl b/source/blender/gpu/shaders/gpu_shader_text_geom.glsl
new file mode 100644
index 00000000000..0acd2106f7a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_text_geom.glsl
@@ -0,0 +1,37 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+layout(points) in;
+layout(triangle_strip, max_vertices = 4) out;
+
+in vec4 pos_rect[];
+in vec4 tex_rect[];
+in vec4 color[];
+
+flat out vec4 color_flat;
+flat out vec4 texCoord_rect;
+noperspective out vec2 texCoord_interp;
+
+void main()
+{
+ color_flat = color[0];
+ texCoord_rect = tex_rect[0];
+
+ gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].xy, 0.0, 1.0));
+ texCoord_interp = vec2(0.0, 0.0);
+ EmitVertex();
+
+ gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].zy, 0.0, 1.0));
+ texCoord_interp = vec2(1.0, 0.0);
+ EmitVertex();
+
+ gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].xw, 0.0, 1.0));
+ texCoord_interp = vec2(0.0, 1.0);
+ EmitVertex();
+
+ gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].zw, 0.0, 1.0));
+ texCoord_interp = vec2(1.0, 1.0);
+ EmitVertex();
+
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl b/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl
new file mode 100644
index 00000000000..8903fd1df57
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl
@@ -0,0 +1,36 @@
+
+layout(points) in;
+layout(triangle_strip, max_vertices = 4) out;
+
+in vec4 pos_rect[];
+in vec4 tex_rect[];
+in vec4 color[];
+
+flat out vec4 color_flat;
+flat out vec4 texCoord_rect;
+noperspective out vec2 texCoord_interp;
+
+void main()
+{
+ color_flat = color[0];
+ texCoord_rect = tex_rect[0];
+ gl_Position.zw = vec2(0.0, 1.0);
+
+ gl_Position.xy = pos_rect[0].xy;
+ texCoord_interp = vec2(0.0, 0.0);
+ EmitVertex();
+
+ gl_Position.xy = pos_rect[0].zy;
+ texCoord_interp = vec2(1.0, 0.0);
+ EmitVertex();
+
+ gl_Position.xy = pos_rect[0].xw;
+ texCoord_interp = vec2(0.0, 1.0);
+ EmitVertex();
+
+ gl_Position.xy = pos_rect[0].zw;
+ texCoord_interp = vec2(1.0, 1.0);
+ EmitVertex();
+
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_simple_vert.glsl b/source/blender/gpu/shaders/gpu_shader_text_simple_vert.glsl
new file mode 100644
index 00000000000..4a2cde71e07
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_text_simple_vert.glsl
@@ -0,0 +1,22 @@
+
+/* Simpler version of gpu_shader_text_vert that supports only 2D translation. */
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec4 pos; /* rect */
+in vec4 tex; /* rect */
+in vec4 col;
+
+out vec4 pos_rect;
+out vec4 tex_rect;
+out vec4 color;
+
+void main()
+{
+ /* Manual mat4*vec2 */
+ pos_rect = ModelViewProjectionMatrix[0].xyxy * pos.xxzz;
+ pos_rect += ModelViewProjectionMatrix[1].xyxy * pos.yyww;
+ pos_rect += ModelViewProjectionMatrix[3].xyxy;
+ tex_rect = tex;
+ color = col;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
index 6129f49ce22..338156f5b68 100644
--- a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
@@ -1,16 +1,17 @@
uniform mat4 ModelViewProjectionMatrix;
-in vec2 pos;
-in vec2 texCoord;
-in vec4 color;
-flat out vec4 color_flat;
-noperspective out vec2 texCoord_interp;
+in vec4 pos; /* rect */
+in vec4 tex; /* rect */
+in vec4 col;
+
+out vec4 pos_rect;
+out vec4 tex_rect;
+out vec4 color;
void main()
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
-
- color_flat = color;
- texCoord_interp = texCoord;
+ pos_rect = pos;
+ tex_rect = tex;
+ color = col;
}
diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp
index 93460559067..c74cbb252ff 100644
--- a/source/blender/ikplugin/intern/itasc_plugin.cpp
+++ b/source/blender/ikplugin/intern/itasc_plugin.cpp
@@ -90,6 +90,7 @@ typedef void (*ErrorCallback)(const iTaSC::ConstraintValues *values, unsigned in
// one structure for each target in the scene
struct IK_Target {
+ const struct EvaluationContext *eval_ctx;
struct Scene *blscene;
iTaSC::MovingFrame* target;
iTaSC::ConstraintSet* constraint;
@@ -107,6 +108,7 @@ struct IK_Target {
float eeRest[4][4]; //end effector initial pose relative to armature
IK_Target() {
+ eval_ctx = NULL;
blscene = NULL;
target = NULL;
constraint = NULL;
@@ -157,6 +159,7 @@ struct IK_Channel {
};
struct IK_Scene {
+ const struct EvaluationContext *eval_ctx;
struct Scene *blscene;
IK_Scene* next;
int numchan; // number of channel in pchan
@@ -177,6 +180,7 @@ struct IK_Scene {
std::vector<IK_Target*> targets;
IK_Scene() {
+ eval_ctx = NULL;
blscene = NULL;
next = NULL;
channels = NULL;
@@ -542,7 +546,7 @@ static void GetJointRotation(KDL::Rotation& boneRot, int type, double *rot)
}
}
-static bool target_callback(const struct EvaluationContext *eval_ctx, const iTaSC::Timestamp& timestamp, const iTaSC::Frame& current, iTaSC::Frame& next, void *param)
+static bool target_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Frame& current, iTaSC::Frame& next, void *param)
{
IK_Target *target = (IK_Target *)param;
// compute next target position
@@ -550,7 +554,7 @@ static bool target_callback(const struct EvaluationContext *eval_ctx, const iTaS
bConstraint *constraint = (bConstraint *)target->blenderConstraint;
float tarmat[4][4];
- BKE_constraint_target_matrix_get(eval_ctx, target->blscene, constraint, 0, CONSTRAINT_OBTYPE_OBJECT, target->owner, tarmat, 1.0);
+ BKE_constraint_target_matrix_get(target->eval_ctx, target->blscene, constraint, 0, CONSTRAINT_OBTYPE_OBJECT, target->owner, tarmat, 1.0);
// rootmat contains the target pose in world coordinate
// if enforce is != 1.0, blend the target position with the end effector position
@@ -577,7 +581,7 @@ static bool target_callback(const struct EvaluationContext *eval_ctx, const iTaS
return true;
}
-static bool base_callback(const struct EvaluationContext *eval_ctx, const iTaSC::Timestamp& timestamp, const iTaSC::Frame& current, iTaSC::Frame& next, void *param)
+static bool base_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Frame& current, iTaSC::Frame& next, void *param)
{
IK_Scene *ikscene = (IK_Scene *)param;
// compute next armature base pose
@@ -619,7 +623,7 @@ static bool base_callback(const struct EvaluationContext *eval_ctx, const iTaSC:
IK_Channel &rootchan = ikscene->channels[0];
// get polar target matrix in world space
- BKE_constraint_target_matrix_get(eval_ctx, ikscene->blscene, ikscene->polarConstraint, 1, CONSTRAINT_OBTYPE_OBJECT, ikscene->blArmature, mat, 1.0);
+ BKE_constraint_target_matrix_get(ikscene->eval_ctx, ikscene->blscene, ikscene->polarConstraint, 1, CONSTRAINT_OBTYPE_OBJECT, ikscene->blArmature, mat, 1.0);
// convert to armature space
mul_m4_m4m4(polemat, imat, mat);
// get the target in world space (was computed before as target object are defined before base object)
@@ -1082,6 +1086,7 @@ static IK_Scene *convert_tree(const struct EvaluationContext *eval_ctx, Scene *b
ikscene = new IK_Scene;
ikscene->blscene = blscene;
+ ikscene->eval_ctx = eval_ctx;
arm = new iTaSC::Armature();
scene = new iTaSC::Scene();
ikscene->channels = new IK_Channel[tree->totchannel];
@@ -1397,7 +1402,7 @@ static IK_Scene *convert_tree(const struct EvaluationContext *eval_ctx, Scene *b
// we can now add the armature
// the armature is based on a moving frame.
// initialize with the correct position in case there is no cache
- base_callback(eval_ctx, iTaSC::Timestamp(), iTaSC::F_identity, initPose, ikscene);
+ base_callback(iTaSC::Timestamp(), iTaSC::F_identity, initPose, ikscene);
ikscene->base = new iTaSC::MovingFrame(initPose);
ikscene->base->setCallback(base_callback, ikscene);
std::string armname;
@@ -1439,6 +1444,7 @@ static IK_Scene *convert_tree(const struct EvaluationContext *eval_ctx, Scene *b
for (t = 0; t < ikscene->targets.size(); t++) {
IK_Target *iktarget = ikscene->targets[t];
iktarget->blscene = blscene;
+ iktarget->eval_ctx = eval_ctx;
condata = (bKinematicConstraint *)iktarget->blenderConstraint->data;
pchan = tree->pchan[iktarget->channel];
unsigned int controltype, bonecnt;
@@ -1458,7 +1464,7 @@ static IK_Scene *convert_tree(const struct EvaluationContext *eval_ctx, Scene *b
mul_m4_m4m4(iktarget->eeRest, invBaseFrame, mat);
iktarget->eeBlend = (!ikscene->polarConstraint && condata->type == CONSTRAINT_IK_COPYPOSE) ? true : false;
// use target_callback to make sure the initPose includes enforce coefficient
- target_callback(eval_ctx, iTaSC::Timestamp(), iTaSC::F_identity, initPose, iktarget);
+ target_callback(iTaSC::Timestamp(), iTaSC::F_identity, initPose, iktarget);
iktarget->target = new iTaSC::MovingFrame(initPose);
iktarget->target->setCallback(target_callback, iktarget);
ret = scene->addObject(iktarget->targetName, iktarget->target);
@@ -1647,7 +1653,7 @@ static void execute_scene(const struct EvaluationContext *eval_ctx, Scene *blsce
}
}
// don't cache if we are reiterating because we don't want to destroy the cache unnecessarily
- ikscene->scene->update(eval_ctx, timestamp, timestep, numstep, false, !reiterate, simulation);
+ ikscene->scene->update(timestamp, timestep, numstep, false, !reiterate, simulation);
if (reiterate) {
// how many times do we reiterate?
for (i = 0; i < ikparam->numiter; i++) {
@@ -1656,11 +1662,11 @@ static void execute_scene(const struct EvaluationContext *eval_ctx, Scene *blsce
{
break;
}
- ikscene->scene->update(eval_ctx, timestamp, timestep, numstep, true, false, simulation);
+ ikscene->scene->update(timestamp, timestep, numstep, true, false, simulation);
}
if (simulation) {
// one more fake iteration to cache
- ikscene->scene->update(eval_ctx, timestamp, 0.0, 1, true, true, true);
+ ikscene->scene->update(timestamp, 0.0, 1, true, true, true);
}
}
// compute constraint error
diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt
index c3950d8eb83..e73f227dec8 100644
--- a/source/blender/imbuf/CMakeLists.txt
+++ b/source/blender/imbuf/CMakeLists.txt
@@ -73,6 +73,7 @@ set(SRC
IMB_colormanagement.h
IMB_imbuf.h
IMB_imbuf_types.h
+ IMB_metadata.h
IMB_moviecache.h
IMB_thumbs.h
intern/IMB_allocimbuf.h
@@ -81,7 +82,6 @@ set(SRC
intern/IMB_filetype.h
intern/IMB_filter.h
intern/IMB_indexer.h
- intern/IMB_metadata.h
intern/imbuf.h
# orphan include
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index a7f793b5b11..e5cd21a3248 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -380,13 +380,13 @@ struct ImBuf *IMB_onehalf(struct ImBuf *ibuf1);
*
* \attention Defined in scaling.c
*/
-struct ImBuf *IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy);
+bool IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy);
/**
*
* \attention Defined in scaling.c
*/
-struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy);
+bool IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy);
/**
*
@@ -399,7 +399,7 @@ void IMB_scaleImBuf_threaded(struct ImBuf *ibuf, unsigned int newx, unsigned int
* \attention Defined in writeimage.c
*/
short IMB_saveiff(struct ImBuf *ibuf, const char *filepath, int flags);
-struct ImBuf *IMB_prepare_write_ImBuf(const bool isfloat, struct ImBuf *ibuf);
+bool IMB_prepare_write_ImBuf(const bool isfloat, struct ImBuf *ibuf);
/**
*
@@ -566,22 +566,6 @@ void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height,
const float col[4], struct ColorManagedDisplay *display,
int x1, int y1, int x2, int y2);
-/**
- *
- * \attention Defined in metadata.c
- */
-/** read the field from the image info into the field
- * \param img - the ImBuf that contains the image data
- * \param key - the key of the field
- * \param value - the data in the field, first one found with key is returned,
- * memory has to be allocated by user.
- * \param len - length of value buffer allocated by user.
- * \return - 1 (true) if ImageInfo present and value for the key found, 0 (false) otherwise
- */
-bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *value, const size_t len);
-bool IMB_metadata_change_field(struct ImBuf *img, const char *key, const char *field);
-void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb);
-
/* exported for image tools in blender, to quickly allocate 32 bits rect */
void *imb_alloc_pixels(unsigned int x,
unsigned int y,
diff --git a/source/blender/imbuf/intern/IMB_metadata.h b/source/blender/imbuf/IMB_metadata.h
index bc0b2c70ecb..6a29fa01594 100644
--- a/source/blender/imbuf/intern/IMB_metadata.h
+++ b/source/blender/imbuf/IMB_metadata.h
@@ -4,7 +4,7 @@
* 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.
+ * 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
@@ -25,7 +25,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/imbuf/intern/IMB_metadata.h
+/** \file blender/imbuf/IMB_metadata.h
* \ingroup imbuf
*/
@@ -33,7 +33,9 @@
#ifndef __IMB_METADATA_H__
#define __IMB_METADATA_H__
+struct anim;
struct ImBuf;
+struct IDProperty;
/** The metadata is a list of key/value pairs (both char *) that can me
* saved in the header of several image formats.
@@ -41,26 +43,36 @@ struct ImBuf;
* 'Software' and 'Description' (png standard) we'll use keys within the
* Blender namespace, so should be called 'Blender::StampInfo' or 'Blender::FrameNum'
* etc...
+ *
+ * The keys & values are stored in ID properties, in the group "metadata".
*/
+/** Ensure that the metadata property is a valid IDProperty object.
+ * This is a no-op when *metadata != NULL.
+ */
+void IMB_metadata_ensure(struct IDProperty **metadata);
+void IMB_metadata_free(struct IDProperty *metadata);
-/* free blender ImMetaData struct */
-void IMB_metadata_free(struct ImBuf *img);
+/** Read the field from the image info into the field.
+ * \param metadata - the IDProperty that contains the metadata
+ * \param key - the key of the field
+ * \param value - the data in the field, first one found with key is returned,
+ * memory has to be allocated by user.
+ * \param len - length of value buffer allocated by user.
+ * \return - 1 (true) if metadata is present and value for the key found, 0 (false) otherwise
+ */
+bool IMB_metadata_get_field(struct IDProperty *metadata, const char *key, char *value, const size_t len);
-/** set user data in the ImMetaData struct, which has to be allocated with IMB_metadata_create
- * before calling this function.
- * \param img - the ImBuf that contains the image data
+/** Set user data in the metadata.
+ * If the field already exists its value is overwritten, otherwise the field
+ * will be added with the given value.
+ * \param metadata - the IDProperty that contains the metadata
* \param key - the key of the field
* \param value - the data to be written to the field. zero terminated string
- * \return - 1 (true) if ImageInfo present, 0 (false) otherwise
*/
-bool IMB_metadata_add_field(struct ImBuf *img, const char *key, const char *value);
+void IMB_metadata_set_field(struct IDProperty *metadata, const char *key, const char *value);
-/** delete the key/field par in the ImMetaData struct.
- * \param img - the ImBuf that contains the image data
- * \param key - the key of the field
- * \return - 1 (true) if delete the key/field, 0 (false) otherwise
- */
-bool IMB_metadata_del_field(struct ImBuf *img, const char *key);
+void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb);
+struct IDProperty *IMB_anim_load_metadata(struct anim *anim);
#endif /* __IMB_METADATA_H__ */
diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h
index c4c4f4405a5..6fa31e122cc 100644
--- a/source/blender/imbuf/intern/IMB_anim.h
+++ b/source/blender/imbuf/intern/IMB_anim.h
@@ -93,6 +93,7 @@
struct _AviMovie;
struct anim_index;
+struct IDProperty;
struct anim {
int ib_flags;
@@ -158,6 +159,8 @@ struct anim {
char colorspace[64];
char suffix[64]; /* MAX_NAME - multiview */
+
+ struct IDProperty *metadata;
};
#endif
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
index 7fc4a65d8d7..faa0b5f7b6e 100644
--- a/source/blender/imbuf/intern/allocimbuf.c
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -219,7 +219,7 @@ void IMB_freeImBuf(ImBuf *ibuf)
IMB_freezbufImBuf(ibuf);
IMB_freezbuffloatImBuf(ibuf);
freeencodedbufferImBuf(ibuf);
- IMB_metadata_free(ibuf);
+ IMB_metadata_free(ibuf->metadata);
colormanage_cache_free(ibuf);
if (ibuf->dds_data.data != NULL) {
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index 5472cae3ef2..f842b69418e 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -68,8 +68,6 @@
#include "MEM_guardedalloc.h"
-#include "BKE_global.h"
-
#ifdef WITH_AVI
# include "AVI_avi.h"
#endif
@@ -82,8 +80,11 @@
#include "IMB_anim.h"
#include "IMB_indexer.h"
+#include "IMB_metadata.h"
#ifdef WITH_FFMPEG
+# include "BKE_global.h" /* ENDIAN_ORDER */
+
# include <libavformat/avformat.h>
# include <libavcodec/avcodec.h>
# include <libavutil/rational.h>
@@ -220,6 +221,7 @@ void IMB_free_anim(struct anim *anim)
free_anim_ffmpeg(anim);
#endif
IMB_free_indices(anim);
+ IMB_metadata_free(anim->metadata);
MEM_freeN(anim);
}
@@ -239,6 +241,26 @@ void IMB_close_anim_proxies(struct anim *anim)
IMB_free_indices(anim);
}
+struct IDProperty *IMB_anim_load_metadata(struct anim *anim)
+{
+#ifdef WITH_FFMPEG
+ AVDictionaryEntry *entry = NULL;
+
+ BLI_assert(anim->pFormatCtx != NULL);
+ av_log(anim->pFormatCtx, AV_LOG_DEBUG, "METADATA FETCH\n");
+
+ while (true) {
+ entry = av_dict_get(anim->pFormatCtx->metadata, "", entry, AV_DICT_IGNORE_SUFFIX);
+ if (entry == NULL) break;
+
+ /* Delay creation of the property group until there is actual metadata to put in there. */
+ IMB_metadata_ensure(&anim->metadata);
+ IMB_metadata_set_field(anim->metadata, entry->key, entry->value);
+ }
+#endif
+ return anim->metadata;
+}
+
struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex, char colorspace[IM_MAX_SPACE])
{
struct anim *anim;
@@ -511,7 +533,7 @@ static int startffmpeg(struct anim *anim)
return -1;
}
- frame_rate = av_get_r_frame_rate_compat(pFormatCtx->streams[videoStream]);
+ frame_rate = av_get_r_frame_rate_compat(pFormatCtx, pFormatCtx->streams[videoStream]);
if (pFormatCtx->streams[videoStream]->nb_frames != 0) {
anim->duration = pFormatCtx->streams[videoStream]->nb_frames;
}
@@ -989,7 +1011,7 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position,
v_st = anim->pFormatCtx->streams[anim->videoStream];
- frame_rate = av_q2d(av_get_r_frame_rate_compat(v_st));
+ frame_rate = av_q2d(av_get_r_frame_rate_compat(anim->pFormatCtx, v_st));
st_time = anim->pFormatCtx->start_time;
pts_time_base = av_q2d(v_st->time_base);
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index 863bce125c5..b2197ecb3b5 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -49,6 +49,7 @@
#include "IMB_filetype.h"
#include "IMB_filter.h"
#include "IMB_moviecache.h"
+#include "IMB_metadata.h"
#include "MEM_guardedalloc.h"
@@ -2176,7 +2177,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet
BLI_rcti_init(&ibuf->invalid_rect, 0, 0, 0, 0);
}
- BLI_lock_thread(LOCK_COLORMANAGE);
+ BLI_thread_lock(LOCK_COLORMANAGE);
/* ensure color management bit fields exists */
if (!ibuf->display_buffer_flags) {
@@ -2194,7 +2195,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet
display_buffer = colormanage_cache_get(ibuf, &cache_view_settings, &cache_display_settings, cache_handle);
if (display_buffer) {
- BLI_unlock_thread(LOCK_COLORMANAGE);
+ BLI_thread_unlock(LOCK_COLORMANAGE);
return display_buffer;
}
@@ -2205,7 +2206,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet
colormanage_cache_put(ibuf, &cache_view_settings, &cache_display_settings, display_buffer, cache_handle);
- BLI_unlock_thread(LOCK_COLORMANAGE);
+ BLI_thread_unlock(LOCK_COLORMANAGE);
return display_buffer;
}
@@ -2244,11 +2245,11 @@ void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *li
void IMB_display_buffer_release(void *cache_handle)
{
if (cache_handle) {
- BLI_lock_thread(LOCK_COLORMANAGE);
+ BLI_thread_lock(LOCK_COLORMANAGE);
colormanage_cache_handle_release(cache_handle);
- BLI_unlock_thread(LOCK_COLORMANAGE);
+ BLI_thread_unlock(LOCK_COLORMANAGE);
}
}
@@ -2964,7 +2965,7 @@ static void imb_partial_display_buffer_update_ex(ImBuf *ibuf,
view_flag = 1 << (cache_view_settings.view - 1);
display_index = cache_display_settings.display - 1;
- BLI_lock_thread(LOCK_COLORMANAGE);
+ BLI_thread_lock(LOCK_COLORMANAGE);
if ((ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) == 0) {
display_buffer = colormanage_cache_get(ibuf,
@@ -2983,7 +2984,7 @@ static void imb_partial_display_buffer_update_ex(ImBuf *ibuf,
memset(ibuf->display_buffer_flags, 0, global_tot_display * sizeof(unsigned int));
ibuf->display_buffer_flags[display_index] |= view_flag;
- BLI_unlock_thread(LOCK_COLORMANAGE);
+ BLI_thread_unlock(LOCK_COLORMANAGE);
}
if (display_buffer == NULL) {
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index 009258079ee..eaf4dfd84b4 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -909,7 +909,7 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context,
stream_size = avio_size(context->iFormatCtx->pb);
- context->frame_rate = av_q2d(av_get_r_frame_rate_compat(context->iStream));
+ context->frame_rate = av_q2d(av_get_r_frame_rate_compat(context->iFormatCtx, context->iStream));
context->pts_time_base = av_q2d(context->iStream->time_base);
while (av_read_frame(context->iFormatCtx, &next_packet) >= 0) {
diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c
index 35c7b6363a1..ef9217fbc8c 100644
--- a/source/blender/imbuf/intern/jpeg.c
+++ b/source/blender/imbuf/intern/jpeg.c
@@ -382,7 +382,8 @@ static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int fla
* the information when we write
* it back to disk.
*/
- IMB_metadata_add_field(ibuf, "None", str);
+ IMB_metadata_ensure(&ibuf->metadata);
+ IMB_metadata_set_field(ibuf->metadata, "None", str);
ibuf->flags |= IB_metadata;
MEM_freeN(str);
goto next_stamp_marker;
@@ -408,7 +409,8 @@ static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int fla
*value = '\0'; /* need finish the key string */
value++;
- IMB_metadata_add_field(ibuf, key, value);
+ IMB_metadata_ensure(&ibuf->metadata);
+ IMB_metadata_set_field(ibuf->metadata, key, value);
ibuf->flags |= IB_metadata;
MEM_freeN(str);
next_stamp_marker:
diff --git a/source/blender/imbuf/intern/metadata.c b/source/blender/imbuf/intern/metadata.c
index da39967a4fe..ef103f7afcf 100644
--- a/source/blender/imbuf/intern/metadata.c
+++ b/source/blender/imbuf/intern/metadata.c
@@ -45,97 +45,69 @@
#include "IMB_metadata.h"
+#define METADATA_MAX_VALUE_LENGTH 1024
-void IMB_metadata_free(struct ImBuf *img)
+void IMB_metadata_ensure(struct IDProperty **metadata)
{
- if (!img)
+ if (*metadata != NULL) {
return;
- if (!img->metadata) {
+ }
+
+ IDPropertyTemplate val;
+ *metadata = IDP_New(IDP_GROUP, &val, "metadata");
+}
+
+void IMB_metadata_free(struct IDProperty *metadata)
+{
+ if (metadata == NULL) {
return;
}
- IDP_FreeProperty(img->metadata);
- MEM_freeN(img->metadata);
+ IDP_FreeProperty(metadata);
+ MEM_freeN(metadata);
}
-bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *field, const size_t len)
+bool IMB_metadata_get_field(struct IDProperty *metadata, const char *key, char *field, const size_t len)
{
IDProperty *prop;
- bool retval = false;
-
- if (!img)
- return false;
- if (!img->metadata)
+ if (metadata == NULL) {
return false;
+ }
- prop = IDP_GetPropertyFromGroup(img->metadata, key);
+ prop = IDP_GetPropertyFromGroup(metadata, key);
if (prop && prop->type == IDP_STRING) {
BLI_strncpy(field, IDP_String(prop), len);
- retval = true;
+ return true;
}
- return retval;
+ return false;
}
void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb)
{
BLI_assert(dimb != simb);
if (simb->metadata) {
- IMB_metadata_free(dimb);
+ IMB_metadata_free(dimb->metadata);
dimb->metadata = IDP_CopyProperty(simb->metadata);
}
}
-bool IMB_metadata_add_field(struct ImBuf *img, const char *key, const char *value)
+void IMB_metadata_set_field(struct IDProperty *metadata, const char *key, const char *value)
{
- IDProperty *prop;
-
- if (!img)
- return false;
+ BLI_assert(metadata);
+ IDProperty *prop = IDP_GetPropertyFromGroup(metadata, key);
- if (!img->metadata) {
- IDPropertyTemplate val;
- img->metadata = IDP_New(IDP_GROUP, &val, "metadata");
+ if (prop != NULL && prop->type != IDP_STRING) {
+ IDP_FreeFromGroup(metadata, prop);
+ prop = NULL;
}
- prop = IDP_NewString(value, key, 512);
- return IDP_AddToGroup(img->metadata, prop);
-}
-
-bool IMB_metadata_del_field(struct ImBuf *img, const char *key)
-{
- IDProperty *prop;
-
- if ((!img) || (!img->metadata))
- return false;
-
- prop = IDP_GetPropertyFromGroup(img->metadata, key);
-
- if (prop) {
- IDP_FreeFromGroup(img->metadata, prop);
+ if (prop == NULL) {
+ prop = IDP_NewString(value, key, METADATA_MAX_VALUE_LENGTH);
+ IDP_AddToGroup(metadata, prop);
}
- return false;
-}
-
-bool IMB_metadata_change_field(struct ImBuf *img, const char *key, const char *field)
-{
- IDProperty *prop;
- if (!img)
- return false;
-
- prop = (img->metadata) ? IDP_GetPropertyFromGroup(img->metadata, key) : NULL;
-
- if (!prop) {
- return (IMB_metadata_add_field(img, key, field));
- }
- else if (prop->type == IDP_STRING) {
- IDP_AssignString(prop, field, 1024);
- return true;
- }
- else {
- return false;
- }
+ IDP_AssignString(prop, value, METADATA_MAX_VALUE_LENGTH);
}
diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c
index 89955711384..daf062f5499 100644
--- a/source/blender/imbuf/intern/moviecache.c
+++ b/source/blender/imbuf/intern/moviecache.c
@@ -513,7 +513,7 @@ void IMB_moviecache_get_cache_segments(MovieCache *cache, int proxy, int render_
*points_r = cache->points;
}
else {
- int totframe = BLI_ghash_size(cache->hash);
+ int totframe = BLI_ghash_len(cache->hash);
int *frames = MEM_callocN(totframe * sizeof(int), "movieclip cache frames");
int a, totseg = 0;
GHashIterator gh_iter;
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 539b9fa45b4..ad04f1fb78d 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -1290,7 +1290,7 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa
return 1;
}
- /* last token is single character channel identifier */
+ /* last token is channel identifier */
len = imb_exr_split_token(name, end, &token);
if (len == 0) {
printf("multilayer read: bad channel name: %s\n", name);
@@ -1319,10 +1319,30 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa
ok = true;
}
}
+ else if (BLI_strcaseeq(token, "red")) {
+ echan->chan_id = 'R';
+ ok = true;
+ }
+ else if (BLI_strcaseeq(token, "green")) {
+ echan->chan_id = 'G';
+ ok = true;
+ }
+ else if (BLI_strcaseeq(token, "blue")) {
+ echan->chan_id = 'B';
+ ok = true;
+ }
+ else if (BLI_strcaseeq(token, "alpha")) {
+ echan->chan_id = 'A';
+ ok = true;
+ }
+ else if (BLI_strcaseeq(token, "depth")) {
+ echan->chan_id = 'Z';
+ ok = true;
+ }
if (ok == false) {
BLI_strncpy(tokenbuf, token, std::min(len + 1, EXR_TOT_MAXNAME));
- printf("multilayer read: channel token too long: %s\n", tokenbuf);
+ printf("multilayer read: unknown channel token: %s\n", tokenbuf);
return 0;
}
}
@@ -1601,14 +1621,13 @@ static bool exr_has_alpha(MultiPartInputFile& file)
static bool imb_exr_is_multilayer_file(MultiPartInputFile& file)
{
- const StringAttribute *comments = file.header(0).findTypedAttribute<StringAttribute>("BlenderMultiChannel");
const ChannelList& channels = file.header(0).channels();
std::set <std::string> layerNames;
/* will not include empty layer names */
channels.layers(layerNames);
- if (comments || layerNames.size() > 1)
+ if (layerNames.size() > 1)
return true;
if (layerNames.size()) {
@@ -1647,7 +1666,7 @@ static void imb_exr_type_by_channels(ChannelList& channels, StringVector& views,
}
else {
*r_singlelayer = false;
- *r_multilayer = true;
+ *r_multilayer = (layerNames.size() > 1);
*r_multiview = false;
return;
}
@@ -1771,12 +1790,13 @@ struct ImBuf *imb_load_openexr(const unsigned char *mem, size_t size, int flags,
const Header & header = file->header(0);
Header::ConstIterator iter;
+ IMB_metadata_ensure(&ibuf->metadata);
for (iter = header.begin(); iter != header.end(); iter++) {
const StringAttribute *attrib = file->header(0).findTypedAttribute <StringAttribute> (iter.name());
/* not all attributes are string attributes so we might get some NULLs here */
if (attrib) {
- IMB_metadata_add_field(ibuf, iter.name(), attrib->value().c_str());
+ IMB_metadata_set_field(ibuf->metadata, iter.name(), attrib->value().c_str());
ibuf->flags |= IB_metadata;
}
}
diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c
index 857f72e10eb..29fbe79d8db 100644
--- a/source/blender/imbuf/intern/png.c
+++ b/source/blender/imbuf/intern/png.c
@@ -759,8 +759,9 @@ ImBuf *imb_loadpng(const unsigned char *mem, size_t size, int flags, char colors
if (flags & IB_metadata) {
png_text *text_chunks;
int count = png_get_text(png_ptr, info_ptr, &text_chunks, NULL);
+ IMB_metadata_ensure(&ibuf->metadata);
for (int i = 0; i < count; i++) {
- IMB_metadata_add_field(ibuf, text_chunks[i].key, text_chunks[i].text);
+ IMB_metadata_set_field(ibuf->metadata, text_chunks[i].key, text_chunks[i].text);
ibuf->flags |= IB_metadata;
}
}
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index 504b59b2b1d..ff92ce15811 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -1550,12 +1550,17 @@ static void scalefast_Z_ImBuf(ImBuf *ibuf, int newx, int newy)
}
}
-struct ImBuf *IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy)
+/**
+ * Return true if \a ibuf is modified.
+ */
+bool IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy)
{
- if (ibuf == NULL) return (NULL);
- if (ibuf->rect == NULL && ibuf->rect_float == NULL) return (ibuf);
+ if (ibuf == NULL) return false;
+ if (ibuf->rect == NULL && ibuf->rect_float == NULL) return false;
- if (newx == ibuf->x && newy == ibuf->y) { return ibuf; }
+ if (newx == ibuf->x && newy == ibuf->y) {
+ return false;
+ }
/* scaleup / scaledown functions below change ibuf->x and ibuf->y
* so we first scale the Z-buffer (if any) */
@@ -1564,7 +1569,7 @@ struct ImBuf *IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int
/* try to scale common cases in a fast way */
/* disabled, quality loss is unacceptable, see report #18609 (ton) */
if (0 && q_scale_linear_interpolation(ibuf, newx, newy)) {
- return ibuf;
+ return true;
}
if (newx && (newx < ibuf->x)) scaledownx(ibuf, newx);
@@ -1572,14 +1577,17 @@ struct ImBuf *IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int
if (newx && (newx > ibuf->x)) scaleupx(ibuf, newx);
if (newy && (newy > ibuf->y)) scaleupy(ibuf, newy);
- return(ibuf);
+ return true;
}
struct imbufRGBA {
float r, g, b, a;
};
-struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy)
+/**
+ * Return true if \a ibuf is modified.
+ */
+bool IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy)
{
unsigned int *rect, *_newrect, *newrect;
struct imbufRGBA *rectf, *_newrectf, *newrectf;
@@ -1590,16 +1598,16 @@ struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned
rect = NULL; _newrect = NULL; newrect = NULL;
rectf = NULL; _newrectf = NULL; newrectf = NULL;
- if (ibuf == NULL) return(NULL);
+ if (ibuf == NULL) return false;
if (ibuf->rect) do_rect = true;
if (ibuf->rect_float) do_float = true;
- if (do_rect == false && do_float == false) return(ibuf);
+ if (do_rect == false && do_float == false) return false;
- if (newx == ibuf->x && newy == ibuf->y) return(ibuf);
+ if (newx == ibuf->x && newy == ibuf->y) return false;
if (do_rect) {
_newrect = MEM_mallocN(newx * newy * sizeof(int), "scalefastimbuf");
- if (_newrect == NULL) return(ibuf);
+ if (_newrect == NULL) return false;
newrect = _newrect;
}
@@ -1607,7 +1615,7 @@ struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned
_newrectf = MEM_mallocN(newx * newy * sizeof(float) * 4, "scalefastimbuf f");
if (_newrectf == NULL) {
if (_newrect) MEM_freeN(_newrect);
- return(ibuf);
+ return false;
}
newrectf = _newrectf;
}
@@ -1643,18 +1651,18 @@ struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned
ibuf->mall |= IB_rect;
ibuf->rect = _newrect;
}
-
+
if (do_float) {
imb_freerectfloatImBuf(ibuf);
ibuf->mall |= IB_rectfloat;
ibuf->rect_float = (float *)_newrectf;
}
-
+
scalefast_Z_ImBuf(ibuf, newx, newy);
-
+
ibuf->x = newx;
ibuf->y = newy;
- return(ibuf);
+ return true;
}
/* ******** threaded scaling ******** */
diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c
index 8c427dff4a3..86e1fba9af7 100644
--- a/source/blender/imbuf/intern/thumbs.c
+++ b/source/blender/imbuf/intern/thumbs.c
@@ -430,16 +430,17 @@ static ImBuf *thumb_create_ex(
IMB_scaleImBuf(img, ex, ey);
}
BLI_snprintf(desc, sizeof(desc), "Thumbnail for %s", uri);
- IMB_metadata_change_field(img, "Description", desc);
- IMB_metadata_change_field(img, "Software", "Blender");
- IMB_metadata_change_field(img, "Thumb::URI", uri);
- IMB_metadata_change_field(img, "Thumb::MTime", mtime);
+ IMB_metadata_ensure(&img->metadata);
+ IMB_metadata_set_field(img->metadata, "Software", "Blender");
+ IMB_metadata_set_field(img->metadata, "Thumb::URI", uri);
+ IMB_metadata_set_field(img->metadata, "Description", desc);
+ IMB_metadata_set_field(img->metadata, "Thumb::MTime", mtime);
if (use_hash) {
- IMB_metadata_change_field(img, "X-Blender::Hash", hash);
+ IMB_metadata_set_field(img->metadata, "X-Blender::Hash", hash);
}
if (ELEM(source, THB_SOURCE_IMAGE, THB_SOURCE_BLEND, THB_SOURCE_FONT)) {
- IMB_metadata_change_field(img, "Thumb::Image::Width", cwidth);
- IMB_metadata_change_field(img, "Thumb::Image::Height", cheight);
+ IMB_metadata_set_field(img->metadata, "Thumb::Image::Width", cwidth);
+ IMB_metadata_set_field(img->metadata, "Thumb::Image::Height", cheight);
}
img->ftype = IMB_FTYPE_PNG;
img->planes = 32;
@@ -589,7 +590,7 @@ ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source
const bool use_hash = thumbhash_from_path(file_path, source, thumb_hash);
- if (IMB_metadata_get_field(img, "Thumb::MTime", mtime, sizeof(mtime))) {
+ if (IMB_metadata_get_field(img->metadata, "Thumb::MTime", mtime, sizeof(mtime))) {
regenerate = (st.st_mtime != atol(mtime));
}
else {
@@ -598,7 +599,7 @@ ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source
}
if (use_hash && !regenerate) {
- if (IMB_metadata_get_field(img, "X-Blender::Hash", thumb_hash_curr, sizeof(thumb_hash_curr))) {
+ if (IMB_metadata_get_field(img->metadata, "X-Blender::Hash", thumb_hash_curr, sizeof(thumb_hash_curr))) {
regenerate = !STREQ(thumb_hash, thumb_hash_curr);
}
else {
@@ -652,7 +653,7 @@ static struct IMBThumbLocks {
void IMB_thumb_locks_acquire(void)
{
- BLI_lock_thread(LOCK_IMAGE);
+ BLI_thread_lock(LOCK_IMAGE);
if (thumb_locks.lock_counter == 0) {
BLI_assert(thumb_locks.locked_paths == NULL);
@@ -663,12 +664,12 @@ void IMB_thumb_locks_acquire(void)
BLI_assert(thumb_locks.locked_paths != NULL);
BLI_assert(thumb_locks.lock_counter > 0);
- BLI_unlock_thread(LOCK_IMAGE);
+ BLI_thread_unlock(LOCK_IMAGE);
}
void IMB_thumb_locks_release(void)
{
- BLI_lock_thread(LOCK_IMAGE);
+ BLI_thread_lock(LOCK_IMAGE);
BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0));
thumb_locks.lock_counter--;
@@ -678,14 +679,14 @@ void IMB_thumb_locks_release(void)
BLI_condition_end(&thumb_locks.cond);
}
- BLI_unlock_thread(LOCK_IMAGE);
+ BLI_thread_unlock(LOCK_IMAGE);
}
void IMB_thumb_path_lock(const char *path)
{
void *key = BLI_strdup(path);
- BLI_lock_thread(LOCK_IMAGE);
+ BLI_thread_lock(LOCK_IMAGE);
BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0));
if (thumb_locks.locked_paths) {
@@ -694,14 +695,14 @@ void IMB_thumb_path_lock(const char *path)
}
}
- BLI_unlock_thread(LOCK_IMAGE);
+ BLI_thread_unlock(LOCK_IMAGE);
}
void IMB_thumb_path_unlock(const char *path)
{
const void *key = path;
- BLI_lock_thread(LOCK_IMAGE);
+ BLI_thread_lock(LOCK_IMAGE);
BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0));
if (thumb_locks.locked_paths) {
@@ -711,5 +712,5 @@ void IMB_thumb_path_unlock(const char *path)
BLI_condition_notify_all(&thumb_locks.cond);
}
- BLI_unlock_thread(LOCK_IMAGE);
+ BLI_thread_unlock(LOCK_IMAGE);
}
diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c
index 00fb1a44dff..efcd7d1f35f 100644
--- a/source/blender/imbuf/intern/thumbs_blend.c
+++ b/source/blender/imbuf/intern/thumbs_blend.c
@@ -37,7 +37,6 @@
#include "BLO_blend_defs.h"
#include "BLO_readfile.h"
-#include "BKE_global.h"
#include "BKE_idcode.h"
#include "BKE_icons.h"
#include "BKE_library.h"
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
index 76a44aa81f7..9dfe926ddff 100644
--- a/source/blender/imbuf/intern/util.c
+++ b/source/blender/imbuf/intern/util.c
@@ -43,8 +43,6 @@
#include "BLI_fileops.h"
#include "BLI_string.h"
-#include "BKE_global.h"
-
#include "imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -53,6 +51,7 @@
#include "IMB_anim.h"
#ifdef WITH_FFMPEG
+#include "BKE_global.h" /* G.debug */
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c
index 84ec2534e7f..e340d082895 100644
--- a/source/blender/imbuf/intern/writeimage.c
+++ b/source/blender/imbuf/intern/writeimage.c
@@ -46,7 +46,7 @@
#include "IMB_colormanagement.h"
#include "IMB_colormanagement_intern.h"
-static ImBuf *prepare_write_imbuf(const ImFileType *type, ImBuf *ibuf)
+static bool prepare_write_imbuf(const ImFileType *type, ImBuf *ibuf)
{
return IMB_prepare_write_ImBuf((type->flag & IM_FTYPE_FLOAT), ibuf);
}
@@ -64,15 +64,11 @@ short IMB_saveiff(struct ImBuf *ibuf, const char *name, int flags)
for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
if (type->save && type->ftype(type, ibuf)) {
- ImBuf *write_ibuf;
short result = false;
- write_ibuf = prepare_write_imbuf(type, ibuf);
+ prepare_write_imbuf(type, ibuf);
- result = type->save(write_ibuf, name, flags);
-
- if (write_ibuf != ibuf)
- IMB_freeImBuf(write_ibuf);
+ result = type->save(ibuf, name, flags);
return result;
}
@@ -83,9 +79,9 @@ short IMB_saveiff(struct ImBuf *ibuf, const char *name, int flags)
return false;
}
-ImBuf *IMB_prepare_write_ImBuf(const bool isfloat, ImBuf *ibuf)
+bool IMB_prepare_write_ImBuf(const bool isfloat, ImBuf *ibuf)
{
- ImBuf *write_ibuf = ibuf;
+ bool changed = false;
if (isfloat) {
/* pass */
@@ -94,8 +90,11 @@ ImBuf *IMB_prepare_write_ImBuf(const bool isfloat, ImBuf *ibuf)
if (ibuf->rect == NULL && ibuf->rect_float) {
ibuf->rect_colorspace = colormanage_colorspace_get_roled(COLOR_ROLE_DEFAULT_BYTE);
IMB_rect_from_float(ibuf);
+ if (ibuf->rect != NULL) {
+ changed = true;
+ }
}
}
- return write_ibuf;
+ return changed;
}
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index f5047352428..72e4597a06e 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -473,6 +473,7 @@ enum {
ID_RECALC_GEOMETRY = 1 << 4,
ID_RECALC_TRANSFORM = 1 << 5,
ID_RECALC_COLLECTIONS = 1 << 6,
+ ID_RECALC_COPY_ON_WRITE = 1 << 7,
/* Special flag to check if SOMETHING was changed. */
ID_RECALC_ALL = (~(int)0),
};
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index c8780c6b4b8..95cbdeadf87 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -393,7 +393,12 @@ typedef enum eRotationModes {
typedef struct bPose {
ListBase chanbase; /* list of pose channels, PoseBones in RNA */
struct GHash *chanhash; /* ghash for quicker string lookups */
-
+
+ /* Flat array of pose channels. It references pointers from
+ * chanbase. Used for quick pose channel lookup from an index.
+ */
+ bPoseChannel **chan_array;
+
short flag, pad;
unsigned int proxy_layer; /* proxy layer: copy from armature, gets synced */
int pad1;
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 407d59f09da..fc3b4afe18d 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -72,7 +72,7 @@ typedef struct Brush {
float rake_factor; /* rake actual data (not texture), used for sculpt */
short blend; /* blend mode */
- short ob_mode; /* & with ob->mode to see if the brush is compatible, use for display only. */
+ short ob_mode; /* eObjectMode: to see if the brush is compatible, use for display only. */
float weight; /* brush weight */
int size; /* brush diameter */
int flag; /* general purpose flag */
diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h
index 806c1ca76fc..2ee0eff7a9c 100644
--- a/source/blender/makesdna/DNA_layer_types.h
+++ b/source/blender/makesdna/DNA_layer_types.h
@@ -97,6 +97,7 @@ typedef struct ViewLayer {
/* Runtime data */
ListBase drawdata; /* ViewLayerEngineData */
+ struct Base **object_bases_array;
} ViewLayer;
typedef struct SceneCollection {
diff --git a/source/blender/makesdna/DNA_meta_types.h b/source/blender/makesdna/DNA_meta_types.h
index f9ba45efef8..d1f001fccc4 100644
--- a/source/blender/makesdna/DNA_meta_types.h
+++ b/source/blender/makesdna/DNA_meta_types.h
@@ -62,7 +62,7 @@ typedef struct MetaElem {
/* Draw_Data: stores pointers used for shader attributes */
float draw_scale_xform[3][4]; /* Matrix of Scale and Translation */
- float draw_stiffness_radius; /* stiffness circle radius (only in edit mode) */
+ float draw_stiffness_radius; /* radius of the stiffness circle (only in edit mode) */
float pad;
} MetaElem;
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index b5ff9f9926a..44627812a21 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -604,7 +604,7 @@ typedef struct ClothModifierData {
struct Cloth *clothObject; /* The internal data structure for cloth. */
struct ClothSimSettings *sim_parms; /* definition is in DNA_cloth_types.h */
struct ClothCollSettings *coll_parms; /* definition is in DNA_cloth_types.h */
- struct PointCache *point_cache; /* definition is in DNA_object_force.h */
+ struct PointCache *point_cache; /* definition is in DNA_object_force_types.h */
struct ListBase ptcaches;
/* XXX nasty hack, remove once hair can be separated from cloth modifier data */
struct ClothHairData *hairdata;
@@ -656,8 +656,7 @@ typedef struct BooleanModifierData {
struct Object *object;
char operation;
- char solver;
- char pad;
+ char pad[2];
char bm_flag;
float double_threshold;
} BooleanModifierData;
@@ -668,11 +667,6 @@ typedef enum {
eBooleanModifierOp_Difference = 2,
} BooleanModifierOp;
-typedef enum {
- eBooleanModifierSolver_Carve = 0,
- eBooleanModifierSolver_BMesh = 1,
-} BooleanSolver;
-
/* bm_flag (only used when G_DEBUG) */
enum {
eBooleanModifierBMeshFlag_BMesh_Separate = (1 << 0),
@@ -801,8 +795,8 @@ typedef enum {
typedef struct FluidsimModifierData {
ModifierData modifier;
- struct FluidsimSettings *fss; /* definition is in DNA_object_fluidsim.h */
- struct PointCache *point_cache; /* definition is in DNA_object_force.h */
+ struct FluidsimSettings *fss; /* definition is in DNA_object_fluidsim_types.h */
+ struct PointCache *point_cache; /* definition is in DNA_object_force_types.h */
} FluidsimModifierData;
typedef struct ShrinkwrapModifierData {
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 0bd36244ffb..63eecebf44a 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1032,12 +1032,12 @@ typedef struct NodeSunBeams {
#define SHD_TANGENT_AXIS_Y 1
#define SHD_TANGENT_AXIS_Z 2
-/* normal map space */
-#define SHD_NORMAL_MAP_TANGENT 0
-#define SHD_NORMAL_MAP_OBJECT 1
-#define SHD_NORMAL_MAP_WORLD 2
-#define SHD_NORMAL_MAP_BLENDER_OBJECT 3
-#define SHD_NORMAL_MAP_BLENDER_WORLD 4
+/* normal map, displacement space */
+#define SHD_SPACE_TANGENT 0
+#define SHD_SPACE_OBJECT 1
+#define SHD_SPACE_WORLD 2
+#define SHD_SPACE_BLENDER_OBJECT 3
+#define SHD_SPACE_BLENDER_WORLD 4
/* math node clamp */
#define SHD_MATH_CLAMP 1
@@ -1077,6 +1077,7 @@ enum {
SHD_SUBSURFACE_CUBIC = 1,
SHD_SUBSURFACE_GAUSSIAN = 2,
SHD_SUBSURFACE_BURLEY = 3,
+ SHD_SUBSURFACE_RANDOM_WALK = 4,
};
/* blur node */
diff --git a/source/blender/makesdna/DNA_object_enums.h b/source/blender/makesdna/DNA_object_enums.h
new file mode 100644
index 00000000000..524c85948f3
--- /dev/null
+++ b/source/blender/makesdna/DNA_object_enums.h
@@ -0,0 +1,52 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file DNA_object_enums.h
+ * \ingroup DNA
+ *
+ * Enums typedef's for use in public headers.
+ */
+
+#ifndef __DNA_OBJECT_ENUMS_H__
+#define __DNA_OBJECT_ENUMS_H__
+
+/* Object.mode */
+typedef enum eObjectMode {
+ OB_MODE_OBJECT = 0,
+ OB_MODE_EDIT = 1 << 0,
+ OB_MODE_SCULPT = 1 << 1,
+ OB_MODE_VERTEX_PAINT = 1 << 2,
+ OB_MODE_WEIGHT_PAINT = 1 << 3,
+ OB_MODE_TEXTURE_PAINT = 1 << 4,
+ OB_MODE_PARTICLE_EDIT = 1 << 5,
+ OB_MODE_POSE = 1 << 6,
+ OB_MODE_GPENCIL = 1 << 7, /* NOTE: Just a dummy to make the UI nicer */
+} eObjectMode;
+
+/* Any mode where the brush system is used. */
+#define OB_MODE_ALL_PAINT (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)
+
+/* Any mode that uses Object.sculpt. */
+#define OB_MODE_ALL_SCULPT (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)
+
+/* Any mode that has data we need to free when switching modes, see: #ED_object_mode_generic_exit */
+#define OB_MODE_ALL_MODE_DATA (OB_MODE_EDIT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_SCULPT)
+
+#endif /* __DNA_OBJECT_ENUMS_H__ */
diff --git a/source/blender/makesdna/DNA_object_fluidsim.h b/source/blender/makesdna/DNA_object_fluidsim_types.h
index 846d5788d63..b305235083a 100644
--- a/source/blender/makesdna/DNA_object_fluidsim.h
+++ b/source/blender/makesdna/DNA_object_fluidsim_types.h
@@ -25,12 +25,12 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file DNA_object_fluidsim.h
+/** \file DNA_object_fluidsim_types.h
* \ingroup DNA
*/
-#ifndef __DNA_OBJECT_FLUIDSIM_H__
-#define __DNA_OBJECT_FLUIDSIM_H__
+#ifndef __DNA_OBJECT_FLUIDSIM_TYPES_H__
+#define __DNA_OBJECT_FLUIDSIM_TYPES_H__
#include "DNA_ID.h"
#include "DNA_defs.h"
@@ -189,6 +189,5 @@ typedef struct FluidsimSettings {
}
#endif
-#endif
-
+#endif /* __DNA_OBJECT_FLUIDSIM_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force_types.h
index 63e1da4f90e..e7ebd3b72d7 100644
--- a/source/blender/makesdna/DNA_object_force.h
+++ b/source/blender/makesdna/DNA_object_force_types.h
@@ -25,12 +25,12 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file DNA_object_force.h
+/** \file DNA_object_force_types.h
* \ingroup DNA
*/
-#ifndef __DNA_OBJECT_FORCE_H__
-#define __DNA_OBJECT_FORCE_H__
+#ifndef __DNA_OBJECT_FORCE_TYPES_H__
+#define __DNA_OBJECT_FORCE_TYPES_H__
#ifdef __cplusplus
extern "C" {
@@ -459,5 +459,5 @@ typedef struct SoftBody {
}
#endif
-#endif
+#endif /* __DNA_OBJECT_FORCE_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 715bd876fef..17dc7ebd2ad 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -33,6 +33,8 @@
#ifndef __DNA_OBJECT_TYPES_H__
#define __DNA_OBJECT_TYPES_H__
+#include "DNA_object_enums.h"
+
#include "DNA_defs.h"
#include "DNA_listBase.h"
#include "DNA_ID.h"
@@ -75,11 +77,19 @@ typedef struct bFaceMap {
} bFaceMap;
/* Object Runtime display data */
+struct ObjectEngineData;
+typedef void (*ObjectEngineDataInitCb)(struct ObjectEngineData *engine_data);
+typedef void (*ObjectEngineDataFreeCb)(struct ObjectEngineData *engine_data);
+
+#
+#
typedef struct ObjectEngineData {
struct ObjectEngineData *next, *prev;
struct DrawEngineType *engine_type;
- void *storage;
- void (*free)(void *storage);
+ /* Only nested data, NOT the engine data itself. */
+ ObjectEngineDataFreeCb free;
+ /* Accumulated recalc flags, which corresponds to ID->recalc flags. */
+ int recalc;
} ObjectEngineData;
#define MAX_VGROUP_NAME 64
@@ -161,9 +171,9 @@ typedef struct Object {
ListBase defbase; /* list of bDeformGroup (vertex groups) names and flag only */
ListBase modifiers; /* list of ModifierData structures */
ListBase fmaps; /* list of facemaps */
-
+
int mode; /* Local object mode */
- int restore_mode; /* Keep track of what mode to return to after toggling a mode */
+ int restore_mode;
/* materials */
struct Material **mat; /* material slots */
@@ -311,14 +321,12 @@ typedef struct Object {
ListBase gpulamp; /* runtime, for glsl lamp display only */
ListBase pc_ids;
- ListBase *duplilist; /* for temporary dupli list storage, only for use by RNA API */
struct RigidBodyOb *rigidbody_object; /* settings for Bullet rigid body */
struct RigidBodyCon *rigidbody_constraint; /* settings for Bullet constraint */
float ima_ofs[2]; /* offset for image empties */
ImageUser *iuser; /* must be non-null when oject is an empty image */
- void *pad4;
ListBase lodlevels; /* contains data for levels of detail */
LodLevel *currentlod;
@@ -704,25 +712,6 @@ enum {
OB_DUPLI_FLAG_RENDER = 1 << 1,
};
-/* ob->mode */
-typedef enum eObjectMode {
- OB_MODE_OBJECT = 0,
- OB_MODE_EDIT = 1 << 0,
- OB_MODE_SCULPT = 1 << 1,
- OB_MODE_VERTEX_PAINT = 1 << 2,
- OB_MODE_WEIGHT_PAINT = 1 << 3,
- OB_MODE_TEXTURE_PAINT = 1 << 4,
- OB_MODE_PARTICLE_EDIT = 1 << 5,
- OB_MODE_POSE = 1 << 6,
- OB_MODE_GPENCIL = 1 << 7, /* NOTE: Just a dummy to make the UI nicer */
-} eObjectMode;
-
-/* any mode where the brush system is used */
-#define OB_MODE_ALL_PAINT (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)
-
-/* any mode that uses ob->sculpt */
-#define OB_MODE_ALL_SCULPT (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)
-
#define MAX_DUPLI_RECUR 8
#ifdef __cplusplus
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index ea7905eb2ad..2c330501820 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -188,11 +188,6 @@ typedef struct ParticleSettings {
/* draw color */
float color_vec_max;
- /* simplification */
- short simplify_flag, simplify_refsize;
- float simplify_rate, simplify_transition;
- float simplify_viewport;
-
/* time and emission */
float sta, end, lifetime, randlife;
float timetweak, courant_target;
@@ -262,7 +257,12 @@ typedef struct ParticleSettings {
short use_modifier_stack;
short pad5;
- int recalc;
+ int pad8;
+
+ float twist;
+ float pad6;
+ struct CurveMapping *twistcurve;
+ void *pad7;
} ParticleSettings;
typedef struct ParticleSystem {
@@ -305,10 +305,8 @@ typedef struct ParticleSystem {
char bb_uvname[3][64]; /* billboard uv name, MAX_CUSTOMDATA_LAYER_NAME */
/* if you change these remember to update array lengths to PSYS_TOT_VG! */
- short vgroup[12], vg_neg, rt3; /* vertex groups, 0==disable, 1==starting index */
-
- /* temporary storage during render */
- struct ParticleRenderData *renderdata;
+ short vgroup[13], vg_neg, rt3; /* vertex groups, 0==disable, 1==starting index */
+ char pad[6];
/* point cache */
struct PointCache *pointcache;
@@ -439,6 +437,7 @@ typedef enum eParticleChildFlag {
PART_CHILD_USE_CLUMP_NOISE = (1<<0),
PART_CHILD_USE_CLUMP_CURVE = (1<<1),
PART_CHILD_USE_ROUGH_CURVE = (1<<2),
+ PART_CHILD_USE_TWIST_CURVE = (1<<3),
} eParticleChildFlag;
/* part->draw_col */
@@ -566,7 +565,7 @@ typedef enum eParticleChildFlag {
#define PART_DUPLIW_CURRENT 1
/* psys->vg */
-#define PSYS_TOT_VG 12
+#define PSYS_TOT_VG 13
#define PSYS_VG_DENSITY 0
#define PSYS_VG_VEL 1
@@ -580,6 +579,7 @@ typedef enum eParticleChildFlag {
#define PSYS_VG_TAN 9
#define PSYS_VG_ROT 10
#define PSYS_VG_EFFECTOR 11
+#define PSYS_VG_TWIST 12
/* ParticleTarget->flag */
#define PTARGET_CURRENT 1
@@ -611,7 +611,8 @@ typedef enum eParticleTextureInfluence {
PAMAP_KINK_AMP = (1<<12),
PAMAP_ROUGH = (1<<9),
PAMAP_LENGTH = (1<<4),
- PAMAP_CHILD = (PAMAP_CLUMP | PAMAP_KINK_FREQ | PAMAP_KINK_AMP | PAMAP_ROUGH | PAMAP_LENGTH),
+ PAMAP_TWIST = (1<<13),
+ PAMAP_CHILD = (PAMAP_CLUMP | PAMAP_KINK_FREQ | PAMAP_KINK_AMP | PAMAP_ROUGH | PAMAP_LENGTH | PAMAP_TWIST),
} eParticleTextureInfluence;
#endif
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index cfa87b17aca..4b27190d79f 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -95,17 +95,28 @@ typedef struct AviCodecData {
typedef enum eFFMpegPreset {
FFM_PRESET_NONE,
- FFM_PRESET_ULTRAFAST,
- FFM_PRESET_SUPERFAST,
- FFM_PRESET_VERYFAST,
- FFM_PRESET_FASTER,
- FFM_PRESET_FAST,
- FFM_PRESET_MEDIUM,
- FFM_PRESET_SLOW,
- FFM_PRESET_SLOWER,
- FFM_PRESET_VERYSLOW,
-} eFFMpegPreset;
+#ifdef DNA_DEPRECATED
+ /* Previously used by h.264 to control encoding speed vs. file size. */
+ FFM_PRESET_ULTRAFAST, /* DEPRECATED */
+ FFM_PRESET_SUPERFAST, /* DEPRECATED */
+ FFM_PRESET_VERYFAST, /* DEPRECATED */
+ FFM_PRESET_FASTER, /* DEPRECATED */
+ FFM_PRESET_FAST, /* DEPRECATED */
+ FFM_PRESET_MEDIUM, /* DEPRECATED */
+ FFM_PRESET_SLOW, /* DEPRECATED */
+ FFM_PRESET_SLOWER, /* DEPRECATED */
+ FFM_PRESET_VERYSLOW, /* DEPRECATED */
+#endif
+
+ /* Used by WEBM/VP9 and h.264 to control encoding speed vs. file size.
+ * WEBM/VP9 use these values directly, whereas h.264 map those to
+ * respectively the MEDIUM, SLOWER, and SUPERFAST presets.
+ */
+ FFM_PRESET_GOOD = 10, /* the default and recommended for most applications */
+ FFM_PRESET_BEST, /* recommended if you have lots of time and want the best compression efficiency */
+ FFM_PRESET_REALTIME, /* recommended for live / fast encoding */
+} eFFMpegPreset;
/* Mapping from easily-understandable descriptions to CRF values.
* Assumes we output 8-bit video. Needs to be remapped if 10-bit
@@ -243,6 +254,7 @@ typedef enum eScenePassType {
SCE_PASS_SUBSURFACE_DIRECT = (1 << 28),
SCE_PASS_SUBSURFACE_INDIRECT = (1 << 29),
SCE_PASS_SUBSURFACE_COLOR = (1 << 30),
+ SCE_PASS_ROUGHNESS = (1 << 31),
} eScenePassType;
#define RE_PASSNAME_COMBINED "Combined"
@@ -1085,7 +1097,6 @@ typedef struct ParticleEditSettings {
int draw_step, fade_frames;
struct Scene *scene;
- struct ViewLayer *view_layer;
struct Object *object;
struct Object *shape_object;
} ParticleEditSettings;
@@ -1642,7 +1653,7 @@ typedef struct Scene {
ListBase base DNA_DEPRECATED;
struct Base *basact DNA_DEPRECATED; /* active base */
- struct Object *obedit; /* name replaces old G.obedit */
+ void *_pad1;
float cursor[3]; /* 3d cursor location */
char _pad[4];
@@ -1853,10 +1864,11 @@ enum {
#define R_STAMP_STRIPMETA 0x1000
#define R_STAMP_MEMORY 0x2000
#define R_STAMP_HIDE_LABELS 0x4000
+#define R_STAMP_FRAME_RANGE 0x8000
#define R_STAMP_ALL (R_STAMP_TIME|R_STAMP_FRAME|R_STAMP_DATE|R_STAMP_CAMERA|R_STAMP_SCENE| \
R_STAMP_NOTE|R_STAMP_MARKER|R_STAMP_FILENAME|R_STAMP_SEQSTRIP| \
R_STAMP_RENDERTIME|R_STAMP_CAMERALENS|R_STAMP_MEMORY| \
- R_STAMP_HIDE_LABELS)
+ R_STAMP_HIDE_LABELS|R_STAMP_FRAME_RANGE)
/* RenderData.alphamode */
#define R_ADDSKY 0
@@ -1963,6 +1975,13 @@ extern const char *RE_engine_id_CYCLES;
#define BASACT(_view_layer) ((_view_layer)->basact)
#define OBACT(_view_layer) (BASACT(_view_layer) ? BASACT(_view_layer)->object: NULL)
+#define OBEDIT_FROM_WORKSPACE(workspace, _view_layer) \
+ (((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 OBEDIT_FROM_VIEW_LAYER(view_layer) \
+ OBEDIT_FROM_OBACT(OBACT(view_layer))
+
#define V3D_CAMERA_LOCAL(v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : NULL)
#define V3D_CAMERA_SCENE(scene, v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : (scene)->camera)
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index 375641d1115..46eb0cbade3 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -71,10 +71,9 @@ typedef struct bScreen {
char swap; /* indicator to survive swap-exchange systems */
char skip_handling; /* set to delay screen handling after switching back from maximized area */
char scrubbing; /* set when scrubbing to avoid some costly updates */
- char pad[6];
+ char pad[2];
- short mainwin; /* screensize subwindow, for screenedges and global menus */
- short subwinactive; /* active subwindow */
+ struct ARegion *active_region; /* active region that has mouse focus */
struct wmTimer *animtimer; /* if set, screen has timer handler added in window */
void *context; /* context callback */
@@ -254,7 +253,7 @@ typedef struct ARegion {
rcti drawrct; /* runtime for partial redraw, same or smaller than winrct */
short winx, winy; /* size */
- short swinid;
+ short visible; /* region is currently visible on screen */
short regiontype; /* window, header, etc. identifier for drawing */
short alignment; /* how it should split */
short flag; /* hide, ... */
diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h
index c95e0a1f54a..c1565bde882 100644
--- a/source/blender/makesdna/DNA_smoke_types.h
+++ b/source/blender/makesdna/DNA_smoke_types.h
@@ -189,7 +189,7 @@ typedef struct SmokeDomainSettings {
char pad[2];
/* Smoke uses only one cache from now on (index [0]), but keeping the array for now for reading old files. */
- struct PointCache *point_cache[2]; /* definition is in DNA_object_force.h */
+ struct PointCache *point_cache[2]; /* definition is in DNA_object_force_types.h */
struct ListBase ptcaches[2];
struct EffectorWeights *effector_weights;
int border_collisions; /* How domain border collisions are handled */
@@ -217,6 +217,9 @@ typedef struct SmokeDomainSettings {
char use_coba;
char coba_field; /* simulation field used for the color mapping */
char pad2;
+
+ float clipping;
+ float pad3;
} SmokeDomainSettings;
diff --git a/source/blender/makesdna/DNA_text_types.h b/source/blender/makesdna/DNA_text_types.h
index 0a9b8c320b5..163dda678d9 100644
--- a/source/blender/makesdna/DNA_text_types.h
+++ b/source/blender/makesdna/DNA_text_types.h
@@ -59,10 +59,6 @@ typedef struct Text {
TextLine *curl, *sell;
int curc, selc;
- char *undo_buf;
- void *pad;
- int undo_pos, undo_len;
-
double mtime;
} Text;
diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h
index 995d7645dc0..0eb54a9b5b3 100644
--- a/source/blender/makesdna/DNA_texture_types.h
+++ b/source/blender/makesdna/DNA_texture_types.h
@@ -86,7 +86,7 @@ typedef struct MTex {
float timefac, lengthfac, clumpfac, dampfac;
float kinkfac, kinkampfac, roughfac, padensfac, gravityfac;
float lifefac, sizefac, ivelfac, fieldfac;
- int pad2;
+ float twistfac;
/* lamp */
float shadowfac;
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 281c16ac892..3da0bdb6ca2 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -412,7 +412,6 @@ typedef struct bTheme {
#define UI_THEMESPACE_START(btheme) (CHECK_TYPE_INLINE(btheme, bTheme *), &((btheme)->tbuts))
#define UI_THEMESPACE_END(btheme) (CHECK_TYPE_INLINE(btheme, bTheme *), (&((btheme)->tclip) + 1))
-/* for the moment only the name. may want to store options with this later */
typedef struct bAddon {
struct bAddon *next, *prev;
char module[64];
@@ -687,12 +686,12 @@ typedef enum eUserpref_UI_Flag {
USER_UIFLAG_DEPRECATED_7 = (1 << 7),
USER_ALLWINCODECS = (1 << 8),
USER_MENUOPENAUTO = (1 << 9),
- USER_ZBUF_CURSOR = (1 << 10),
+ USER_DEPTH_CURSOR = (1 << 10),
USER_AUTOPERSP = (1 << 11),
USER_LOCKAROUND = (1 << 12),
USER_GLOBALUNDO = (1 << 13),
USER_ORBIT_SELECTION = (1 << 14),
- USER_ZBUF_ORBIT = (1 << 15),
+ USER_DEPTH_NAVIGATE = (1 << 15),
USER_HIDE_DOT = (1 << 16),
USER_SHOW_ROTVIEWICON = (1 << 17),
USER_SHOW_VIEWPORTNAME = (1 << 18),
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 9ec34ac3823..f03ff4ba8b7 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -59,6 +59,7 @@ struct ReportList;
struct Report;
struct uiLayout;
struct Stereo3dFormat;
+struct UndoStep;
#define OP_MAX_TYPENAME 64
#define KMAP_MAX_NAME 64
@@ -155,6 +156,8 @@ typedef struct wmWindowManager {
ListBase timers; /* active timers */
struct wmTimer *autosavetimer; /* timer for auto save */
+ struct UndoStack *undo_stack; /* all undo history (runtime only). */
+
char is_interface_locked; /* indicates whether interface is locked for user interaction */
char par[7];
@@ -180,6 +183,7 @@ typedef struct wmWindow {
struct wmWindow *next, *prev;
void *ghostwin; /* don't want to include ghost.h stuff */
+ void *gwnctx; /* don't want to include gawin stuff */
struct Scene *scene; /* The scene displayed in this window. */
struct Scene *new_scene; /* temporary when switching */
@@ -197,8 +201,7 @@ typedef struct wmWindow {
short modalcursor; /* the current modal cursor */
short grabcursor; /* cursor grab mode */
short addmousemove; /* internal: tag this for extra mousemove event, makes cursors/buttons active on UI switching */
- short multisamples; /* amount of samples for OpenGL FSA the ghost window was created with, if zero no FSA */
- short pad[3];
+ short pad[4];
int winid; /* winid also in screens, is for retrieving this window after read */
@@ -208,8 +211,6 @@ typedef struct wmWindow {
struct wmEvent *eventstate; /* storage for event system */
- struct wmSubWindow *curswin; /* internal for wm_subwindow.c only */
-
struct wmGesture *tweak; /* internal for wm_operators.c */
/* Input Method Editor data - complex character input (esp. for asian character input)
@@ -223,7 +224,6 @@ typedef struct wmWindow {
ListBase handlers; /* window+screen handlers, handled last */
ListBase modalhandlers; /* priority handlers, handled first */
- ListBase subwindows; /* opengl stuff for sub windows, see notes in wm_subwindow.c */
ListBase gesture; /* gesture stuff */
struct Stereo3dFormat *stereo3d_format; /* properties for stereoscopic displays */
@@ -315,13 +315,16 @@ typedef struct wmKeyMap {
char idname[64]; /* global editor keymaps, or for more per space/region */
short spaceid; /* same IDs as in DNA_space_types.h */
short regionid; /* see above */
+ char owner_id[64]; /* optional, see: #wmOwnerID */
short flag; /* general flags */
short kmi_id; /* last kmi id */
/* runtime */
- int (*poll)(struct bContext *); /* verify if enabled in the current context */
- const void *modal_items; /* for modal, EnumPropertyItem for now */
+ /** Verify if enabled in the current context, use #WM_keymap_poll instead of direct calls. */
+ int (*poll)(struct bContext *);
+ /** For modal, #EnumPropertyItem for now. */
+ const void *modal_items;
} wmKeyMap;
/* wmKeyMap.flag */
diff --git a/source/blender/makesdna/DNA_workspace_types.h b/source/blender/makesdna/DNA_workspace_types.h
index adc3c1fef2b..82aa7b8b81c 100644
--- a/source/blender/makesdna/DNA_workspace_types.h
+++ b/source/blender/makesdna/DNA_workspace_types.h
@@ -77,6 +77,12 @@ typedef struct WorkSpaceLayout {
char name[64] DNA_PRIVATE_WORKSPACE; /* MAX_NAME */
} WorkSpaceLayout;
+/** Optional tags, which features to use, aligned with #bAddon names by convention. */
+typedef struct wmOwnerID {
+ struct wmOwnerID *next, *prev;
+ char name[64] DNA_PRIVATE_WORKSPACE; /* MAX_NAME */
+} wmOwnerID;
+
typedef struct WorkSpace {
ID id;
@@ -86,6 +92,9 @@ typedef struct WorkSpace {
ListBase hook_layout_relations DNA_PRIVATE_WORKSPACE_READ_WRITE; /* WorkSpaceDataRelation */
ListBase scene_viewlayer_relations DNA_PRIVATE_WORKSPACE_READ_WRITE; /* WorkSpaceDataRelation */
+ /* Feature tagging (use for addons) */
+ ListBase owner_ids DNA_PRIVATE_WORKSPACE_READ_WRITE; /* wmOwnerID */
+
/* Custom transform orientations */
ListBase transform_orientations DNA_PRIVATE_WORKSPACE;
@@ -151,6 +160,7 @@ typedef struct WorkSpaceInstanceHook {
typedef enum eWorkSpaceFlags {
WORKSPACE_USE_SCENE_SETTINGS = (1 << 0),
+ WORKSPACE_USE_FILTER_BY_ORIGIN = (1 << 1),
} eWorkSpaceFlags;
#endif /* __DNA_WORKSPACE_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h
index 2ab99617ee8..3361e50e257 100644
--- a/source/blender/makesdna/DNA_world_types.h
+++ b/source/blender/makesdna/DNA_world_types.h
@@ -163,6 +163,12 @@ enum {
WO_AOMUL = 3,
};
+enum {
+ WO_MIST_QUADRATIC = 0,
+ WO_MIST_LINEAR = 1,
+ WO_MIST_INVERSE_QUADRATIC = 2,
+};
+
/* ao_samp_method - methods for sampling the AO hemi */
#define WO_AOSAMP_CONSTANT 0
#define WO_AOSAMP_HALTON 1
diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt
index 8c758c33dc5..5b8dcd97108 100644
--- a/source/blender/makesdna/intern/CMakeLists.txt
+++ b/source/blender/makesdna/intern/CMakeLists.txt
@@ -107,6 +107,7 @@ set(INC_SYS
set(SRC
../../blenlib/intern/BLI_ghash.c
+ ../../blenlib/intern/BLI_ghash_utils.c
../../blenlib/intern/BLI_mempool.c
../../blenlib/intern/endian_switch.c
../../blenlib/intern/hash_mm2a.c
diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c
index 199bb75d099..c9385f98584 100644
--- a/source/blender/makesdna/intern/dna_genfile.c
+++ b/source/blender/makesdna/intern/dna_genfile.c
@@ -57,7 +57,7 @@
* \section dna_genfile Overview
*
* - please note: no builtin security to detect input of double structs
- * - if you want a struct not to be in DNA file: add two hash marks above it (#<enter>#<enter>)
+ * - if you want a struct not to be in DNA file: add two hash marks above it `(#<enter>#<enter>)`.
*
* Structure DNA data is added to each blender file and to each executable, this to detect
* in .blend files new variables in structs, changed array sizes, etc. It's also used for
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 00ff7451dbb..e66ea248e7c 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -86,8 +86,8 @@ static const char *includefiles[] = {
"DNA_modifier_types.h",
"DNA_lattice_types.h",
"DNA_object_types.h",
- "DNA_object_force.h",
- "DNA_object_fluidsim.h",
+ "DNA_object_force_types.h",
+ "DNA_object_fluidsim_types.h",
"DNA_world_types.h",
"DNA_scene_types.h",
"DNA_view3d_types.h",
@@ -1315,8 +1315,8 @@ int main(int argc, char **argv)
#include "DNA_modifier_types.h"
#include "DNA_lattice_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
-#include "DNA_object_fluidsim.h"
+#include "DNA_object_force_types.h"
+#include "DNA_object_fluidsim_types.h"
#include "DNA_world_types.h"
#include "DNA_scene_types.h"
#include "DNA_view3d_types.h"
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 1f9b80974e7..d5752ff3e5e 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -299,6 +299,8 @@ extern StructRNA RNA_HemiLamp;
extern StructRNA RNA_Histogram;
extern StructRNA RNA_HookModifier;
extern StructRNA RNA_ID;
+extern StructRNA RNA_IDOverrideStatic;
+extern StructRNA RNA_IDOverrideStaticProperty;
extern StructRNA RNA_IKParam;
extern StructRNA RNA_Image;
extern StructRNA RNA_ImageFormatSettings;
@@ -724,6 +726,7 @@ extern StructRNA RNA_WipeSequence;
extern StructRNA RNA_WireframeModifier;
extern StructRNA RNA_WoodTexture;
extern StructRNA RNA_WorkSpace;
+extern StructRNA RNA_wmOwnerIDs;
extern StructRNA RNA_World;
extern StructRNA RNA_WorldAmbientOcclusion;
extern StructRNA RNA_WorldLighting;
@@ -902,6 +905,9 @@ bool RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index);
bool RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop); /* without lib check, only checks the flag */
bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop);
bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop);
+bool RNA_property_overridable(PointerRNA *ptr, PropertyRNA *prop);
+bool RNA_property_overridden(PointerRNA *ptr, PropertyRNA *prop);
+bool RNA_property_comparable(PointerRNA *ptr, PropertyRNA *prop);
bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop); /* slow, use with care */
void RNA_property_update(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop);
@@ -1282,6 +1288,13 @@ typedef enum eRNAOverrideMatchResult {
RNA_OVERRIDE_MATCH_RESULT_RESTORED = 1 << 1,
} eRNAOverrideMatchResult;
+typedef enum eRNAOverrideStatus {
+ RNA_OVERRIDE_STATUS_OVERRIDABLE = 1 << 0, /* The property is overridable. */
+ RNA_OVERRIDE_STATUS_OVERRIDDEN = 1 << 1, /* The property is overridden. */
+ RNA_OVERRIDE_STATUS_MANDATORY = 1 << 2, /* Overriding this property is mandatory when creating an override. */
+ RNA_OVERRIDE_STATUS_LOCKED = 1 << 3, /* The override status of this property is locked. */
+} eRNAOverrideStatus;
+
bool RNA_struct_override_matches(
struct PointerRNA *ptr_local, struct PointerRNA *ptr_reference, const char *root_path,
struct IDOverrideStatic *override, const eRNAOverrideMatch flags,
@@ -1304,9 +1317,11 @@ struct IDOverrideStaticPropertyOperation *RNA_property_override_property_operati
PointerRNA *ptr, PropertyRNA *prop, const short operation, const int index,
const bool strict, bool *r_strict, bool *r_created);
-void RNA_property_override_status(
- PointerRNA *ptr, PropertyRNA *prop, const int index,
- bool *r_overridable, bool *r_overridden, bool *r_mandatory, bool *r_locked);
+eRNAOverrideStatus RNA_property_override_status(PointerRNA *ptr, PropertyRNA *prop, const int index);
+
+void RNA_struct_state_owner_set(const char *name);
+const char *RNA_struct_state_owner_get(void);
+
#ifdef __cplusplus
}
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index e0824281656..77d9aabd661 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -158,7 +158,7 @@ typedef enum PropertySubType {
/* Make sure enums are updated with these */
/* HIGHEST FLAG IN USE: 1 << 31
- * FREE FLAGS: 3, 9, 11, 13, 14, 15, 30 */
+ * FREE FLAGS: 9, 11, 13, 14, 15, 30 */
typedef enum PropertyFlag {
/* editable means the property is editable in the user
* interface, properties are editable by default except
@@ -179,6 +179,10 @@ typedef enum PropertyFlag {
/* Means the property can be overriden by a local 'proxy' of some linked datablock. */
PROP_OVERRIDABLE_STATIC = (1 << 2),
+ /* Forbid usage of this property in comparison (& hence override) code.
+ * Useful e.g. for collections of data like mesh's geometry, particles, etc. */
+ PROP_NO_COMPARISON = (1 << 3),
+
/* This flag means when the property's widget is in 'textedit' mode, it will be updated
* after every typed char, instead of waiting final validation. Used e.g. for text searchbox.
* It will also cause UI_BUT_VALUE_CLEAR to be set for text buttons. We could add an own flag
@@ -411,22 +415,46 @@ typedef struct ParameterDynAlloc {
/* Function */
typedef enum FunctionFlag {
- FUNC_NO_SELF = (1 << 0), /* for static functions */
- FUNC_USE_SELF_TYPE = (1 << 1), /* for class methods, only used when FUNC_NO_SELF is set */
+ /***** Options affecting callback signature. *****/
+ /* Those add additionnal parameters at the beginning of the C callback, like that:
+ * rna_my_func([ID *_selfid],
+ * [<DNA_STRUCT> *self|StructRNA *type],
+ * [Main *bmain],
+ * [bContext *C],
+ * [ReportList *reports],
+ * <other RNA-defined parameters>);
+ */
+ /* Pass ID owning 'self' data (i.e. ptr->id.data, might be same as self in case data is an ID...). */
+ FUNC_USE_SELF_ID = (1 << 11),
+
+ /* Do not pass the object (DNA struct pointer) from which it is called, used to define static or class functions. */
+ FUNC_NO_SELF = (1 << 0),
+ /* Pass RNA type, used to define class functions, only valid when FUNC_NO_SELF is set. */
+ FUNC_USE_SELF_TYPE = (1 << 1),
+
+ /* Pass Main, bContext and/or ReportList. */
FUNC_USE_MAIN = (1 << 2),
FUNC_USE_CONTEXT = (1 << 3),
FUNC_USE_REPORTS = (1 << 4),
- FUNC_USE_SELF_ID = (1 << 11),
- FUNC_ALLOW_WRITE = (1 << 12),
- /* registering */
+
+ /***** Registering of python subclasses. *****/
+ /* This function is part of the registerable class' interface, and can be implemented/redefined in python. */
FUNC_REGISTER = (1 << 5),
+ /* Subclasses can choose not to implement this function. */
FUNC_REGISTER_OPTIONAL = FUNC_REGISTER | (1 << 6),
+ /* If not set, the python function implementing this call is not allowed to write into data-blocks.
+ * Except for WindowManager and Screen currently, see rna_id_write_error() in bpy_rna.c */
+ FUNC_ALLOW_WRITE = (1 << 12),
- /* internal flags */
+ /***** Internal flags. *****/
+ /* UNUSED CURRENTLY? ??? */
FUNC_BUILTIN = (1 << 7),
+ /* UNUSED CURRENTLY. ??? */
FUNC_EXPORT = (1 << 8),
+ /* Function has been defined at runtime, not statically in RNA source code. */
FUNC_RUNTIME = (1 << 9),
+ /* UNUSED CURRENTLY? Function owns its identifier and description strings, and has to free them when deleted. */
FUNC_FREE_POINTERS = (1 << 10),
} FunctionFlag;
@@ -481,7 +509,6 @@ typedef struct ExtensionRNA {
StructRNA *srna;
StructCallbackFunc call;
StructFreeFunc free;
-
} ExtensionRNA;
#ifdef __cplusplus
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 1ae8acd5844..dd062ac5ace 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -794,12 +794,12 @@ static int rna_ID_is_updated_data_get(PointerRNA *ptr)
return ((data->recalc & ID_RECALC_ALL) != 0);
}
-static PointerRNA rna_ID_override_reference_get(PointerRNA *ptr)
+static IDProperty *rna_IDPropertyWrapPtr_idprops(PointerRNA *ptr, bool UNUSED(create))
{
- ID *id = (ID *)ptr->data;
- ID *reference = (id && id->override_static) ? id->override_static->reference : NULL;
-
- return reference ? rna_pointer_inherit_refine(ptr, ID_code_to_RNA_type(GS(reference->name)), reference) : PointerRNA_NULL;
+ if (ptr == NULL) {
+ return NULL;
+ }
+ return ptr->data;
}
#else
@@ -998,6 +998,33 @@ static void rna_def_image_preview(BlenderRNA *brna)
RNA_def_function_ui_description(func, "Reload the preview from its source path");
}
+static void rna_def_ID_override_static_property(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "IDOverrideStaticProperty", NULL);
+ RNA_def_struct_ui_text(srna, "ID Static Override Property", "Description of an overridden property");
+
+ prop = RNA_def_string(srna, "rna_path", NULL, INT_MAX, "RNA Path", "RNA path leading to that property, from owning ID");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* For now. */
+}
+
+ static void rna_def_ID_override_static(BlenderRNA *brna)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, "IDOverrideStatic", NULL);
+ RNA_def_struct_ui_text(srna, "ID Static Override", "Struct gathering all data needed by statically overridden IDs");
+
+ RNA_def_pointer(srna, "reference", "ID", "Reference ID", "Linked ID used as reference by this override");
+
+ RNA_def_collection(srna, "properties", "IDOverrideStaticProperty", "Properties",
+ "List of overridden properties");
+
+ rna_def_ID_override_static_property(brna);
+}
+
static void rna_def_ID(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1064,11 +1091,8 @@ static void rna_def_ID(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Library", "Library file the data-block is linked from");
- prop = RNA_def_pointer(srna, "override_static_reference", "ID",
- "Override Reference", "Reference linked data-block overridden by this one");
- RNA_def_property_pointer_sdna(prop, NULL, "override_static->reference");
+ prop = RNA_def_pointer(srna, "override_static", "IDOverrideStatic", "Static Override", "Static override data");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_pointer_funcs(prop, "rna_ID_override_reference_get", NULL, NULL, NULL);
prop = RNA_def_pointer(srna, "preview", "ImagePreview", "Preview",
"Preview image and icon of this data-block (None if not supported for this type of data)");
@@ -1165,6 +1189,20 @@ static void rna_def_library(BlenderRNA *brna)
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_CONTEXT);
RNA_def_function_ui_description(func, "Reload this library and all its linked data-blocks");
}
+
+/**
+ * \attention This is separate from the above. It allows for RNA functions to
+ * return an IDProperty *. See MovieClip.metadata for a usage example.
+ **/
+static void rna_def_idproperty_wrap_ptr(BlenderRNA *brna)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, "IDPropertyWrapPtr", NULL);
+ RNA_def_struct_idprops_func(srna, "rna_IDPropertyWrapPtr_idprops");
+ RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES);
+}
+
void RNA_def_ID(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1178,10 +1216,12 @@ void RNA_def_ID(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Any Type", "RNA type used for pointers to any possible data");
rna_def_ID(brna);
+ rna_def_ID_override_static(brna);
rna_def_image_preview(brna);
rna_def_ID_properties(brna);
rna_def_ID_materials(brna);
rna_def_library(brna);
+ rna_def_idproperty_wrap_ptr(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index b8dbc69f352..4a267313ac9 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -451,8 +451,9 @@ static void *rna_idproperty_check_ex(PropertyRNA **prop, PointerRNA *ptr, const
return idprop;
}
- else
+ else {
return return_rnaprop ? *prop : NULL;
+ }
}
{
@@ -1842,7 +1843,7 @@ bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
return ((flag & PROP_EDITABLE) &&
(flag & PROP_REGISTER) == 0 &&
(!id || ((!ID_IS_LINKED(id) || (prop->flag & PROP_LIB_EXCEPTION)) &&
- (!id->override_static || (prop->flag & PROP_OVERRIDABLE_STATIC)))));
+ (!id->override_static || RNA_property_overridable(ptr, prop)))));
}
/**
@@ -1863,7 +1864,7 @@ bool RNA_property_editable_info(PointerRNA *ptr, PropertyRNA *prop, const char *
else {
flag = prop->flag;
if ((flag & PROP_EDITABLE) == 0 || (flag & PROP_REGISTER)) {
- *r_info = "This property is for internal use only and can't be edited.";
+ *r_info = N_("This property is for internal use only and can't be edited");
}
}
@@ -1871,13 +1872,13 @@ bool RNA_property_editable_info(PointerRNA *ptr, PropertyRNA *prop, const char *
if (id) {
if (ID_IS_LINKED(id) && (prop->flag & PROP_LIB_EXCEPTION) == 0) {
if (!(*r_info)[0]) {
- *r_info = "Can't edit this property from a linked data-block.";
+ *r_info = N_("Can't edit this property from a linked data-block.");
}
return false;
}
- if (id->override_static != NULL && (prop->flag & PROP_OVERRIDABLE_STATIC) == 0) {
+ if (id->override_static != NULL && !RNA_property_overridable(ptr, prop)) {
if (!(*r_info)[0]) {
- *r_info = "Can't edit this property from an override data-block.";
+ *r_info = N_("Can't edit this property from an override data-block.");
}
return false;
}
@@ -1954,6 +1955,34 @@ 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_edtiable_flag() usually). */
+bool RNA_property_overridable(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
+{
+ prop = rna_ensure_property(prop);
+
+ return !(prop->flag & PROP_NO_COMPARISON) && (prop->flag & PROP_OVERRIDABLE_STATIC);
+}
+
+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_static == NULL) {
+ return false;
+ }
+
+ return (BKE_override_static_property_find(id->override_static, rna_path) != NULL);
+}
+
+bool RNA_property_comparable(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
+{
+ prop = rna_ensure_property(prop);
+
+ return !(prop->flag & PROP_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)
@@ -7053,8 +7082,21 @@ bool RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop,
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)) {
- false;
+ return false;
}
IDOverrideStaticPropertyOperation opop = {
@@ -7136,10 +7178,13 @@ bool RNA_struct_equals(PointerRNA *ptr_a, PointerRNA *ptr_b, eRNACompareMode mod
* 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(
- PointerRNA *ptr_a, PointerRNA *ptr_b, PropertyRNA *prop, PropertyRNA *prop_a, PropertyRNA *prop_b, const char *rna_path,
- eRNACompareMode mode, IDOverrideStatic *override, const int flags, eRNAOverrideMatchResult *r_report_flags)
+ PointerRNA *ptr_a, PointerRNA *ptr_b, PropertyRNA *prop, PropertyRNA *prop_a, PropertyRNA *prop_b,
+ const char *rna_path, eRNACompareMode mode,
+ IDOverrideStatic *override, const int flags, eRNAOverrideMatchResult *r_report_flags)
{
if (prop != NULL) {
BLI_assert(prop_a == NULL && prop_b == NULL);
@@ -7151,6 +7196,10 @@ static int rna_property_override_diff(
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)) {
@@ -7228,7 +7277,7 @@ static int rna_property_override_diff(
bool override_changed = false;
int diff_flags = flags;
- if ((RNA_property_flag(prop_a) & PROP_OVERRIDABLE_STATIC) == 0) {
+ if (!RNA_property_overridable(ptr_a, prop_a)) {
diff_flags &= ~RNA_OVERRIDE_COMPARE_CREATE;
}
const int diff = override_diff(
@@ -7414,7 +7463,7 @@ bool RNA_struct_override_matches(
continue;
}
- if (ignore_non_overridable && !(prop_local->flag & PROP_OVERRIDABLE_STATIC)) {
+ if (ignore_non_overridable && !RNA_property_overridable(ptr_local, prop_local)) {
continue;
}
@@ -7665,29 +7714,30 @@ IDOverrideStaticPropertyOperation *RNA_property_override_property_operation_get(
return BKE_override_static_property_operation_get(op, operation, NULL, NULL, index, index, strict, r_strict, r_created);
}
-void RNA_property_override_status(
- PointerRNA *ptr, PropertyRNA *prop, const int index,
- bool *r_overridable, bool *r_overridden, bool *r_mandatory, bool *r_locked)
+eRNAOverrideStatus RNA_property_override_status(PointerRNA *ptr, PropertyRNA *prop, const int index)
{
-#define SET_RET(_name, _val) if (_name != NULL) *_name = (_val)
-
- SET_RET(r_overridable, false);
- SET_RET(r_overridden, false);
- SET_RET(r_mandatory, false);
- SET_RET(r_locked, false);
+ int override_status = 0;
if (!ptr || !prop || !ptr->id.data || !((ID *)ptr->id.data)->override_static) {
- return;
+ return override_status;
}
- SET_RET(r_overridable, (prop->flag & PROP_OVERRIDABLE_STATIC) && (prop->flag & PROP_EDITABLE));
+ if (RNA_property_overridable(ptr, prop) && RNA_property_editable_flag(ptr, prop)) {
+ override_status |= RNA_OVERRIDE_STATUS_OVERRIDABLE;
+ }
- if (r_overridden || r_mandatory || r_locked) {
- IDOverrideStaticPropertyOperation *opop = RNA_property_override_property_operation_find(ptr, prop, index, false, NULL);
- SET_RET(r_overridden, opop != NULL);
- SET_RET(r_mandatory, (opop->flag & IDOVERRIDESTATIC_FLAG_MANDATORY) != 0);
- SET_RET(r_locked, (opop->flag & IDOVERRIDESTATIC_FLAG_LOCKED) != 0);
+ IDOverrideStaticPropertyOperation *opop = RNA_property_override_property_operation_find(ptr, prop, index, false, NULL);
+ if (opop != NULL) {
+ override_status |= RNA_OVERRIDE_STATUS_OVERRIDDEN;
+ if (opop->flag & IDOVERRIDESTATIC_FLAG_MANDATORY) {
+ override_status |= RNA_OVERRIDE_STATUS_MANDATORY;
+ }
+ if (opop->flag & IDOVERRIDESTATIC_FLAG_LOCKED) {
+ override_status |= RNA_OVERRIDE_STATUS_LOCKED;
+ }
}
+
+ return override_status;
}
@@ -7710,3 +7760,22 @@ bool RNA_path_resolved_create(
return false;
}
}
+
+static char rna_struct_state_owner[64];
+void RNA_struct_state_owner_set(const char *name)
+{
+ if (name) {
+ BLI_strncpy(rna_struct_state_owner, name, sizeof(rna_struct_state_owner));
+ }
+ else {
+ rna_struct_state_owner[0] = '\0';
+ }
+}
+
+const char *RNA_struct_state_owner_get(void)
+{
+ if (rna_struct_state_owner[0]) {
+ return rna_struct_state_owner;
+ }
+ return NULL;
+}
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index 3d11e7bb723..3c940e3dcbf 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -520,7 +520,7 @@ static void rna_KeyingSet_paths_clear(KeyingSet *keyingset, ReportList *reports)
/* needs wrapper function to push notifier */
static NlaTrack *rna_NlaTrack_new(AnimData *adt, bContext *C, NlaTrack *track)
{
- NlaTrack *new_track = add_nlatrack(adt, track);
+ NlaTrack *new_track = BKE_nlatrack_add(adt, track);
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL);
@@ -536,7 +536,7 @@ static void rna_NlaTrack_remove(AnimData *adt, bContext *C, ReportList *reports,
return;
}
- free_nlatrack(&adt->nla_tracks, track);
+ BKE_nlatrack_free(&adt->nla_tracks, track);
RNA_POINTER_INVALIDATE(track_ptr);
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_REMOVED, NULL);
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 5336a63fb76..1ad33b683b7 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -436,7 +436,6 @@ static void rna_Brush_icon_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi
br->id.icon_id = 0;
if (br->flag & BRUSH_CUSTOM_ICON) {
- BKE_previewimg_id_ensure(&br->id);
BKE_icon_changed(BKE_icon_id_ensure(&br->id));
}
diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c
index e6e1c714008..04e7f64712e 100644
--- a/source/blender/makesrna/intern/rna_depsgraph.c
+++ b/source/blender/makesrna/intern/rna_depsgraph.c
@@ -34,10 +34,11 @@
#include "rna_internal.h"
-#include "DEG_depsgraph.h"
-
#include "DNA_object_types.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
#define STATS_MAX_SIZE 16384
#ifdef RNA_RUNTIME
@@ -80,6 +81,14 @@ static PointerRNA rna_DepsgraphIter_parent_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_Object, dupli_parent);
}
+static PointerRNA rna_DepsgraphIter_particle_system_get(PointerRNA *ptr)
+{
+ BLI_Iterator *iterator = ptr->data;
+ DEGObjectIterData *deg_iter = (DEGObjectIterData *)iterator->data;
+ return rna_pointer_inherit_refine(ptr, &RNA_ParticleSystem,
+ deg_iter->dupli_object_current->particle_system);
+}
+
static void rna_DepsgraphIter_persistent_id_get(PointerRNA *ptr, int *persistent_id)
{
BLI_Iterator *iterator = ptr->data;
@@ -240,6 +249,13 @@ static ID *rna_Depsgraph_evaluated_id_get(Depsgraph *depsgraph, ID *id_orig)
return DEG_get_evaluated_id(depsgraph, id_orig);
}
+static PointerRNA rna_Depsgraph_view_layer_get(PointerRNA *ptr)
+{
+ Depsgraph *depsgraph = (Depsgraph *)ptr->data;
+ ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
+ return rna_pointer_inherit_refine(ptr, &RNA_ViewLayer, view_layer);
+}
+
#else
static void rna_def_depsgraph_iter(BlenderRNA *brna)
@@ -269,6 +285,12 @@ static void rna_def_depsgraph_iter(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_pointer_funcs(prop, "rna_DepsgraphIter_parent_get", NULL, NULL, NULL);
+ prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "ParticleSystem");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Particle System", "Particle system that this object was instanced from");
+ RNA_def_property_pointer_funcs(prop, "rna_DepsgraphIter_particle_system_get", NULL, NULL, NULL);
+
prop = RNA_def_property(srna, "persistent_id", PROP_INT, PROP_NONE);
RNA_def_property_ui_text(prop, "Persistent ID",
"Persistent identifier for inter-frame matching of objects with motion blur");
@@ -358,6 +380,11 @@ static void rna_def_depsgraph(BlenderRNA *brna)
"rna_Depsgraph_duplis_end",
"rna_Depsgraph_duplis_get",
NULL, NULL, NULL, NULL);
+
+ prop = RNA_def_property(srna, "view_layer", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "ViewLayer");
+ RNA_def_property_pointer_funcs(prop, "rna_Depsgraph_view_layer_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Scene layer", "");
}
void RNA_def_depsgraph(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c
index 596aff6de8f..466a01a7271 100644
--- a/source/blender/makesrna/intern/rna_dynamicpaint.c
+++ b/source/blender/makesrna/intern/rna_dynamicpaint.c
@@ -34,7 +34,7 @@
#include "DNA_dynamicpaint_types.h"
#include "DNA_modifier_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -723,11 +723,11 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_WAVE_OPEN_BORDERS);
RNA_def_property_ui_text(prop, "Open Borders", "Pass waves through mesh edges");
-
/* cache */
prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_pointer_sdna(prop, NULL, "pointcache");
+ RNA_def_property_struct_type(prop, "PointCache");
RNA_def_property_ui_text(prop, "Point Cache", "");
/* is cache used */
diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c
index 271ead13197..a75aceb6f7e 100644
--- a/source/blender/makesrna/intern/rna_fluidsim.c
+++ b/source/blender/makesrna/intern/rna_fluidsim.c
@@ -26,7 +26,7 @@
#include <stdlib.h>
-#include "DNA_object_fluidsim.h"
+#include "DNA_object_fluidsim_types.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 563d68cb6f9..8bc82e90999 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -35,6 +35,7 @@
#define RNA_MAGIC ((int)~0)
+struct Depsgraph;
struct FreestyleSettings;
struct ID;
struct IDOverrideStatic;
@@ -476,8 +477,8 @@ PointerRNA rna_pointer_inherit_refine(struct PointerRNA *ptr, struct StructRNA *
int rna_parameter_size(struct PropertyRNA *parm);
struct Mesh *rna_Main_meshes_new_from_object(
- struct Main *bmain, struct ReportList *reports, struct Scene *sce, struct ViewLayer *view_layer,
- struct Object *ob, int apply_modifiers, int settings, int calc_tessface, int calc_undeformed);
+ struct Main *bmain, struct ReportList *reports, struct Depsgraph *depsgraph,
+ struct Object *ob, int apply_modifiers, int calc_tessface, int calc_undeformed);
/* XXX, these should not need to be defined here~! */
struct MTex *rna_mtex_texture_slots_add(struct ID *self, struct bContext *C, struct ReportList *reports);
diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c
index 47f5d037d09..7d09f30ed6a 100644
--- a/source/blender/makesrna/intern/rna_layer.c
+++ b/source/blender/makesrna/intern/rna_layer.c
@@ -94,7 +94,7 @@ static void rna_SceneCollection_name_set(PointerRNA *ptr, const char *value)
{
Scene *scene = (Scene *)ptr->id.data;
SceneCollection *sc = (SceneCollection *)ptr->data;
- BKE_collection_rename(scene, sc, value);
+ BKE_collection_rename(&scene->id, sc, value);
}
static PointerRNA rna_SceneCollection_objects_get(CollectionPropertyIterator *iter)
@@ -141,6 +141,23 @@ static int rna_SceneCollection_move_into(ID *id, SceneCollection *sc_src, Main *
return 1;
}
+static SceneCollection *rna_SceneCollection_duplicate(
+ ID *id, SceneCollection *scene_collection, Main *bmain, bContext *C, ReportList *reports)
+{
+ if (scene_collection == BKE_collection_master(id)) {
+ BKE_report(reports, RPT_ERROR, "The master collection can't be duplicated");
+ return NULL;
+ }
+
+ SceneCollection *scene_collection_new = BKE_collection_duplicate(id, scene_collection);
+
+ DEG_relations_tag_update(bmain);
+ /* Don't use id here, since the layer collection may come from a group. */
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, CTX_data_scene(C));
+
+ return scene_collection_new;
+}
+
static SceneCollection *rna_SceneCollection_new(
ID *id, SceneCollection *sc_parent, Main *bmain, const char *name)
{
@@ -384,6 +401,7 @@ RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(shadow_method)
RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(shadow_size)
RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(shadow_high_bitdepth)
RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(taa_samples)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(taa_render_samples)
RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(gi_diffuse_bounces)
RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(gi_cubemap_resolution)
RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(gi_visibility_resolution)
@@ -634,9 +652,9 @@ static int rna_LayerCollection_name_length(PointerRNA *ptr)
static void rna_LayerCollection_name_set(PointerRNA *ptr, const char *value)
{
- Scene *scene = (Scene *)ptr->id.data;
+ ID *owner_id = (ID *)ptr->id.data;
SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection;
- BKE_collection_rename(scene, sc, value);
+ BKE_collection_rename(owner_id, sc, value);
}
static PointerRNA rna_LayerCollection_objects_get(CollectionPropertyIterator *iter)
@@ -716,6 +734,23 @@ static Group *rna_LayerCollection_create_group(
return group;
}
+static LayerCollection *rna_LayerCollection_duplicate(
+ ID *id, LayerCollection *layer_collection, Main *bmain, bContext *C, ReportList *reports)
+{
+ if (layer_collection->scene_collection == BKE_collection_master(id)) {
+ BKE_report(reports, RPT_ERROR, "The master collection can't be duplicated");
+ return NULL;
+ }
+
+ LayerCollection *layer_collection_new = BKE_layer_collection_duplicate(id, layer_collection);
+
+ DEG_relations_tag_update(bmain);
+ /* Don't use id here, since the layer collection may come from a group. */
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, CTX_data_scene(C));
+
+ return layer_collection_new;
+}
+
static int rna_LayerCollections_active_collection_index_get(PointerRNA *ptr)
{
ViewLayer *view_layer = (ViewLayer *)ptr->data;
@@ -842,10 +877,14 @@ static int rna_ViewLayer_objects_selected_skip(CollectionPropertyIterator *iter,
static PointerRNA rna_ViewLayer_depsgraph_get(PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
- ViewLayer *view_layer = (ViewLayer *)ptr->data;
- Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false);
- return rna_pointer_inherit_refine(ptr, &RNA_Depsgraph, depsgraph);
+ ID *id = ptr->id.data;
+ if (GS(id->name) == ID_SCE) {
+ Scene *scene = (Scene *)id;
+ ViewLayer *view_layer = (ViewLayer *)ptr->data;
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false);
+ return rna_pointer_inherit_refine(ptr, &RNA_Depsgraph, depsgraph);
+ }
+ return PointerRNA_NULL;
}
static void rna_LayerObjects_selected_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
@@ -857,18 +896,19 @@ static void rna_LayerObjects_selected_begin(CollectionPropertyIterator *iter, Po
static void rna_ViewLayer_update_tagged(ViewLayer *UNUSED(view_layer), bContext *C)
{
Depsgraph *graph = CTX_data_depsgraph(C);
- DEG_OBJECT_ITER(graph, ob, DEG_ITER_OBJECT_MODE_VIEWPORT,
- DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
- DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET |
- DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY |
- DEG_ITER_OBJECT_FLAG_VISIBLE |
- DEG_ITER_OBJECT_FLAG_DUPLI)
+ DEG_OBJECT_ITER_BEGIN(
+ graph, ob, DEG_ITER_OBJECT_MODE_VIEWPORT,
+ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
+ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET |
+ DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY |
+ DEG_ITER_OBJECT_FLAG_VISIBLE |
+ DEG_ITER_OBJECT_FLAG_DUPLI)
{
/* Don't do anything, we just need to run the iterator to flush
* the base info to the objects. */
UNUSED_VARS(ob);
}
- DEG_OBJECT_ITER_END
+ DEG_OBJECT_ITER_END;
}
static void rna_ObjectBase_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -880,7 +920,7 @@ static void rna_ObjectBase_select_update(Main *UNUSED(bmain), Scene *UNUSED(scen
static char *rna_ViewRenderSettings_path(PointerRNA *UNUSED(ptr))
{
- return BLI_sprintfN("viewport_render");
+ return BLI_sprintfN("view_render");
}
static void rna_ViewRenderSettings_engine_set(PointerRNA *ptr, int value)
@@ -1079,6 +1119,12 @@ static void rna_def_scene_collection(BlenderRNA *brna)
parm = RNA_def_pointer(func, "sc_dst", "SceneCollection", "Collection", "Collection to insert into");
parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "duplicate", "rna_SceneCollection_duplicate");
+ RNA_def_function_ui_description(func, "Create a copy of the collection");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "result", "SceneCollection", "", "Newly created collection");
+ RNA_def_function_return(func, parm);
}
static void rna_def_layer_collection_override(BlenderRNA *brna)
@@ -1199,12 +1245,19 @@ static void rna_def_view_layer_engine_settings_eevee(BlenderRNA *brna)
prop = RNA_def_property(srna, "taa_samples", PROP_INT, PROP_NONE);
RNA_def_property_int_funcs(prop, "rna_LayerEngineSettings_Eevee_taa_samples_get",
"rna_LayerEngineSettings_Eevee_taa_samples_set", NULL);
- RNA_def_property_ui_text(prop, "Viewport Samples", "Number of temporal samples, unlimited if 0, "
- "disabled if 1");
+ RNA_def_property_ui_text(prop, "Viewport Samples", "Number of samples, unlimited if 0");
RNA_def_property_range(prop, 0, INT_MAX);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+ prop = RNA_def_property(srna, "taa_render_samples", PROP_INT, PROP_NONE);
+ RNA_def_property_int_funcs(prop, "rna_LayerEngineSettings_Eevee_taa_render_samples_get",
+ "rna_LayerEngineSettings_Eevee_taa_render_samples_set", NULL);
+ RNA_def_property_ui_text(prop, "Render Samples", "Number of samples per pixels for rendering");
+ RNA_def_property_range(prop, 1, INT_MAX);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
/* Screen Space Subsurface Scattering */
prop = RNA_def_property(srna, "sss_enable", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_sss_enable_get",
@@ -1986,6 +2039,12 @@ static void rna_def_layer_collection(BlenderRNA *brna)
parm = RNA_def_pointer(func, "result", "Group", "", "Newly created Group");
RNA_def_function_return(func, parm);
+ func = RNA_def_function(srna, "duplicate", "rna_LayerCollection_duplicate");
+ RNA_def_function_ui_description(func, "Create a copy of the collection");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "result", "LayerCollection", "", "Newly created collection");
+ RNA_def_function_return(func, parm);
+
/* Flags */
prop = RNA_def_property(srna, "selectable", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_SELECTABLE);
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 00585d5de18..42c8eceeb16 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -301,27 +301,17 @@ static Mesh *rna_Main_meshes_new(Main *bmain, const char *name)
}
/* copied from Mesh_getFromObject and adapted to RNA interface */
-/* settings: 1 - preview, 2 - render */
Mesh *rna_Main_meshes_new_from_object(
- Main *bmain, ReportList *reports, Scene *sce, ViewLayer *view_layer,
- Object *ob, int apply_modifiers, int settings, int calc_tessface, int calc_undeformed)
+ Main *bmain, ReportList *reports, Depsgraph *depsgraph,
+ Object *ob, int apply_modifiers, int calc_tessface, int calc_undeformed)
{
EvaluationContext eval_ctx;
+ Scene *sce = DEG_get_evaluated_scene(depsgraph);
- /* XXX: This should never happen, but render pipeline is not ready to give
- * proper view_layer, and will always pass NULL here. For until we port
- * pipeline form SceneRenderLayer to ViewLayer we have this stub to prevent
- * some obvious crashes.
- * - sergey -
- */
- if (view_layer == NULL) {
- view_layer = sce->view_layers.first;
- }
-
- DEG_evaluation_context_init(&eval_ctx, settings);
- eval_ctx.ctime = (float)sce->r.cfra + sce->r.subframe;
- eval_ctx.view_layer = view_layer;
- eval_ctx.depsgraph = BKE_scene_get_depsgraph(sce, view_layer, false);
+ DEG_evaluation_context_init(&eval_ctx, DEG_get_mode(depsgraph));
+ eval_ctx.ctime = DEG_get_ctime(depsgraph);
+ eval_ctx.view_layer = DEG_get_evaluated_view_layer(depsgraph);
+ eval_ctx.depsgraph = depsgraph;
switch (ob->type) {
case OB_FONT:
@@ -335,7 +325,7 @@ Mesh *rna_Main_meshes_new_from_object(
return NULL;
}
- return BKE_mesh_new_from_object(&eval_ctx, bmain, sce, ob, apply_modifiers, settings, calc_tessface, calc_undeformed);
+ return BKE_mesh_new_from_object(&eval_ctx, bmain, sce, ob, apply_modifiers, calc_tessface, calc_undeformed);
}
static Lamp *rna_Main_lamps_new(Main *bmain, const char *name, int type)
@@ -896,12 +886,6 @@ void RNA_def_main_meshes(BlenderRNA *brna, PropertyRNA *cprop)
PropertyRNA *parm;
PropertyRNA *prop;
- static const EnumPropertyItem mesh_type_items[] = {
- {eModifierMode_Realtime, "PREVIEW", 0, "Preview", "Apply modifier preview settings"},
- {eModifierMode_Render, "RENDER", 0, "Render", "Apply modifier render settings"},
- {0, NULL, 0, NULL, NULL}
- };
-
RNA_def_property_srna(cprop, "BlendDataMeshes");
srna = RNA_def_struct(brna, "BlendDataMeshes", NULL);
RNA_def_struct_sdna(srna, "Main");
@@ -918,16 +902,12 @@ void RNA_def_main_meshes(BlenderRNA *brna, PropertyRNA *cprop)
func = RNA_def_function(srna, "new_from_object", "rna_Main_meshes_new_from_object");
RNA_def_function_ui_description(func, "Add a new mesh created from object with modifiers applied");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene within which to evaluate modifiers");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
- parm = RNA_def_pointer(func, "view_layer", "ViewLayer", "", "Scene layer within which to evaluate modifiers");
+ parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "Dependency Graph", "Evaluated dependency graph within wich to evaluate modifiers");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
parm = RNA_def_pointer(func, "object", "Object", "", "Object to create mesh from");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
parm = RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- parm = RNA_def_enum(func, "settings", mesh_type_items, 0, "", "Modifier settings to apply");
- RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
RNA_def_boolean(func, "calc_tessface", true, "Calculate Tessellation", "Calculate tessellation faces");
RNA_def_boolean(func, "calc_undeformed", false, "Calculate Undeformed", "Calculate undeformed vertex coordinates");
parm = RNA_def_pointer(func, "mesh", "Mesh", "",
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 440af0d0e8e..bf6e13e587c 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -92,13 +92,15 @@ const EnumPropertyItem rna_enum_ramp_blend_items[] = {
#include "BKE_texture.h"
#include "BKE_node.h"
#include "BKE_paint.h"
+#include "BKE_scene.h"
+#include "BKE_workspace.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "ED_node.h"
#include "ED_image.h"
-#include "BKE_scene.h"
+#include "ED_screen.h"
static void rna_Material_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
@@ -201,15 +203,27 @@ static void rna_Material_active_paint_texture_index_update(Main *bmain, Scene *s
if (ma->texpaintslot) {
Image *image = ma->texpaintslot[ma->paint_active_slot].ima;
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+ wmWindow *win = ED_screen_window_find(sc, bmain->wm.first);
+ if (win == NULL) {
+ continue;
+ }
+
+ Object *obedit = NULL;
+ {
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+ ViewLayer *view_layer = BKE_workspace_view_layer_get(workspace, scene);
+ obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
+ }
+
ScrArea *sa;
for (sa = sc->areabase.first; sa; sa = sa->next) {
SpaceLink *sl;
for (sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)sl;
-
- if (!sima->pin)
- ED_space_image_set(sima, scene, scene->obedit, image);
+ if (!sima->pin) {
+ ED_space_image_set(sima, scene, obedit, image);
+ }
}
}
}
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 9a6eddf20ef..579c865e679 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -34,7 +34,7 @@
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
@@ -1963,12 +1963,6 @@ static void rna_def_modifier_boolean(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static const EnumPropertyItem prop_solver_items[] = {
- {eBooleanModifierSolver_BMesh, "BMESH", 0, "BMesh", "Use the BMesh boolean solver"},
- {eBooleanModifierSolver_Carve, "CARVE", 0, "Carve", "Use the Carve boolean solver"},
- {0, NULL, 0, NULL, NULL}
- };
-
srna = RNA_def_struct(brna, "BooleanModifier", "Modifier");
RNA_def_struct_ui_text(srna, "Boolean Modifier", "Boolean operations modifier");
RNA_def_struct_sdna(srna, "BooleanModifierData");
@@ -1985,11 +1979,6 @@ static void rna_def_modifier_boolean(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Operation", "");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
- prop = RNA_def_property(srna, "solver", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, prop_solver_items);
- RNA_def_property_ui_text(prop, "Solver", "");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
prop = RNA_def_property(srna, "double_threshold", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "double_threshold");
RNA_def_property_range(prop, 0, 1.0f);
diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c
index 850b1cd706b..c663119eb42 100644
--- a/source/blender/makesrna/intern/rna_movieclip.c
+++ b/source/blender/makesrna/intern/rna_movieclip.c
@@ -33,6 +33,7 @@
#include "DNA_movieclip_types.h"
#include "DNA_scene_types.h"
+#include "RNA_access.h"
#include "RNA_define.h"
#include "rna_internal.h"
@@ -44,6 +45,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_metadata.h"
#ifdef RNA_RUNTIME
@@ -103,6 +105,22 @@ static void rna_MovieClipUser_proxy_render_settings_update(Main *UNUSED(bmain),
}
}
+static PointerRNA rna_MovieClip_metadata_get(MovieClip *clip)
+{
+ if (clip == NULL || clip->anim == NULL) {
+ return PointerRNA_NULL;
+ }
+
+ IDProperty *metadata = IMB_anim_load_metadata(clip->anim);
+ if (metadata == NULL) {
+ return PointerRNA_NULL;
+ }
+
+ PointerRNA ptr;
+ RNA_pointer_create(NULL, &RNA_IDPropertyWrapPtr, metadata, &ptr);
+ return ptr;
+}
+
#else
static void rna_def_movieclip_proxy(BlenderRNA *brna)
@@ -257,6 +275,8 @@ static void rna_def_movieclip(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ FunctionRNA *func;
+ PropertyRNA *parm;
static const EnumPropertyItem clip_source_items[] = {
{MCLIP_SRC_SEQUENCE, "SEQUENCE", 0, "Image Sequence", "Multiple image files, as a sequence"},
@@ -348,6 +368,14 @@ static void rna_def_movieclip(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "ColorManagedInputColorspaceSettings");
RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings");
+ /* metadata */
+ func = RNA_def_function(srna, "metadata", "rna_MovieClip_metadata_get");
+ RNA_def_function_ui_description(func, "Retrieve metadata of the movie file");
+ /* return type */
+ parm = RNA_def_pointer(func, "metadata", "IDPropertyWrapPtr", "", "Dict-like object containing the metadata");
+ RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
+ RNA_def_function_return(func, parm);
+
rna_def_animdata_common(srna);
}
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
index a14508ecb18..1301762a4bc 100644
--- a/source/blender/makesrna/intern/rna_nla.c
+++ b/source/blender/makesrna/intern/rna_nla.c
@@ -370,7 +370,7 @@ static FCurve *rna_NlaStrip_fcurve_find(NlaStrip *strip, ReportList *reports, co
static NlaStrip *rna_NlaStrip_new(NlaTrack *track, bContext *C, ReportList *reports, const char *UNUSED(name),
int start, bAction *action)
{
- NlaStrip *strip = add_nlastrip(action);
+ NlaStrip *strip = BKE_nlastrip_new(action);
if (strip == NULL) {
BKE_report(reports, RPT_ERROR, "Unable to create new strip");
@@ -383,7 +383,7 @@ static NlaStrip *rna_NlaStrip_new(NlaTrack *track, bContext *C, ReportList *repo
if (BKE_nlastrips_add_strip(&track->strips, strip) == 0) {
BKE_report(reports, RPT_ERROR,
"Unable to add strip (the track does not have any space to accommodate this new strip)");
- free_nlastrip(NULL, strip);
+ BKE_nlastrip_free(NULL, strip);
return NULL;
}
@@ -424,7 +424,7 @@ static void rna_NlaStrip_remove(NlaTrack *track, bContext *C, ReportList *report
return;
}
- free_nlastrip(&track->strips, strip);
+ BKE_nlastrip_free(&track->strips, strip);
RNA_POINTER_INVALIDATE(strip_ptr);
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_REMOVED, NULL);
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 2b2c6998eb4..012545cb5d2 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -67,6 +67,7 @@
#include "NOD_composite.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
const EnumPropertyItem rna_enum_node_socket_in_out_items[] = {
{ SOCK_IN, "IN", 0, "Input", "" },
@@ -2306,9 +2307,15 @@ static void rna_NodeSocketStandard_vector_range(PointerRNA *ptr, float *min, flo
static void rna_NodeSocket_value_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeSocket *sock = ptr->data;
+
if (ntree->type == NTREE_SHADER) {
- DEG_id_tag_update_ex(bmain, ptr->id.data, DEG_TAG_SHADING_UPDATE);
+ DEG_id_tag_update_ex(bmain, &ntree->id, DEG_TAG_SHADING_UPDATE);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING, NULL);
+
+ if (sock->type == SOCK_STRING) {
+ rna_NodeSocket_update(bmain, scene, ptr);
+ }
}
else {
rna_NodeSocket_update(bmain, scene, ptr);
@@ -2717,7 +2724,7 @@ static int rna_Node_image_has_views_get(PointerRNA *ptr)
if (!ima || !(ima->rr)) return 0;
- return BLI_listbase_count_ex(&ima->rr->views, 2) > 1;
+ return BLI_listbase_count_at_most(&ima->rr->views, 2) > 1;
}
static const EnumPropertyItem *renderresult_views_add_enum(RenderView *rv)
@@ -3128,16 +3135,20 @@ static int point_density_vertex_color_source_from_shader(NodeShaderTexPointDensi
}
void rna_ShaderNodePointDensity_density_cache(bNode *self,
- Scene *scene,
- ViewLayer *view_layer,
- int settings)
+ Depsgraph *depsgraph)
{
NodeShaderTexPointDensity *shader_point_density = self->storage;
PointDensity *pd = &shader_point_density->pd;
- if (scene == NULL) {
+
+ if (depsgraph == NULL) {
return;
}
+ EvaluationContext eval_ctx;
+ DEG_evaluation_context_init_from_depsgraph(&eval_ctx,
+ depsgraph,
+ DEG_get_mode(depsgraph));
+
/* Make sure there's no cached data. */
BKE_texture_pointdensity_free_data(pd);
RE_point_density_free(pd);
@@ -3166,15 +3177,12 @@ void rna_ShaderNodePointDensity_density_cache(bNode *self,
shader_point_density->cached_resolution = shader_point_density->resolution;
/* Single-threaded sampling of the voxel domain. */
- RE_point_density_cache(scene,
- view_layer, pd,
- settings == 1);
+ RE_point_density_cache(&eval_ctx,
+ pd);
}
void rna_ShaderNodePointDensity_density_calc(bNode *self,
- Scene *scene,
- ViewLayer *view_layer,
- int settings,
+ Depsgraph *depsgraph,
int *length,
float **values)
{
@@ -3182,11 +3190,16 @@ void rna_ShaderNodePointDensity_density_calc(bNode *self,
PointDensity *pd = &shader_point_density->pd;
const int resolution = shader_point_density->cached_resolution;
- if (scene == NULL) {
+ if (depsgraph == NULL) {
*length = 0;
return;
}
+ EvaluationContext eval_ctx;
+ DEG_evaluation_context_init_from_depsgraph(&eval_ctx,
+ depsgraph,
+ DEG_get_mode(depsgraph));
+
/* TODO(sergey): Will likely overflow, but how to pass size_t via RNA? */
*length = 4 * resolution * resolution * resolution;
@@ -3195,9 +3208,9 @@ void rna_ShaderNodePointDensity_density_calc(bNode *self,
}
/* Single-threaded sampling of the voxel domain. */
- RE_point_density_sample(scene, view_layer, pd,
+ RE_point_density_sample(&eval_ctx,
+ pd,
resolution,
- settings == 1,
*values);
/* We're done, time to clean up. */
@@ -3207,20 +3220,25 @@ void rna_ShaderNodePointDensity_density_calc(bNode *self,
}
void rna_ShaderNodePointDensity_density_minmax(bNode *self,
- Scene *scene,
- ViewLayer *view_layer,
- int settings,
+ Depsgraph *depsgraph,
float r_min[3],
float r_max[3])
{
NodeShaderTexPointDensity *shader_point_density = self->storage;
PointDensity *pd = &shader_point_density->pd;
- if (scene == NULL) {
+
+ if (depsgraph == NULL) {
zero_v3(r_min);
zero_v3(r_max);
return;
}
- RE_point_density_minmax(scene, view_layer, pd, settings == 1, r_min, r_max);
+
+ EvaluationContext eval_ctx;
+ DEG_evaluation_context_init_from_depsgraph(&eval_ctx,
+ depsgraph,
+ DEG_get_mode(depsgraph));
+
+ RE_point_density_minmax(&eval_ctx, pd, r_min, r_max);
}
#else
@@ -3312,11 +3330,18 @@ static const EnumPropertyItem node_script_mode_items[] = {
};
static const EnumPropertyItem node_principled_distribution_items[] = {
- { SHD_GLOSSY_GGX, "GGX", 0, "GGX", "" },
- { SHD_GLOSSY_MULTI_GGX, "MULTI_GGX", 0, "Multiscatter GGX", "" },
+ {SHD_GLOSSY_GGX, "GGX", 0, "GGX", ""},
+ {SHD_GLOSSY_MULTI_GGX, "MULTI_GGX", 0, "Multiscatter GGX", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static const EnumPropertyItem node_subsurface_method_items[] = {
+ {SHD_SUBSURFACE_BURLEY, "BURLEY", 0, "Christensen-Burley", "Approximation to physically based volume scattering"},
+ {SHD_SUBSURFACE_RANDOM_WALK, "RANDOM_WALK", 0, "Random Walk", "Volumetric approximation to physically based volume scattering"},
{ 0, NULL, 0, NULL, NULL }
};
+
/* -- Common nodes ---------------------------------------------------------- */
static void def_group_input(StructRNA *srna)
@@ -4135,13 +4160,6 @@ static void def_sh_tex_pointdensity(StructRNA *srna)
{0, NULL, 0, NULL, NULL}
};
- /* TODO(sergey): Use some mnemonic names for the hardcoded values here. */
- static const EnumPropertyItem calc_mode_items[] = {
- {0, "VIEWPORT", 0, "Viewport", "Canculate density using viewport settings"},
- {1, "RENDER", 0, "Render", "Canculate duplis using render settings"},
- {0, NULL, 0, NULL, NULL}
- };
-
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "Object");
@@ -4203,15 +4221,11 @@ static void def_sh_tex_pointdensity(StructRNA *srna)
func = RNA_def_function(srna, "cache_point_density", "rna_ShaderNodePointDensity_density_cache");
RNA_def_function_ui_description(func, "Cache point density data for later calculation");
- RNA_def_pointer(func, "scene", "Scene", "", "");
- RNA_def_pointer(func, "view_layer", "ViewLayer", "", "");
- RNA_def_enum(func, "settings", calc_mode_items, 1, "", "Calculate density for rendering");
+ RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "");
func = RNA_def_function(srna, "calc_point_density", "rna_ShaderNodePointDensity_density_calc");
RNA_def_function_ui_description(func, "Calculate point density");
- RNA_def_pointer(func, "scene", "Scene", "", "");
- RNA_def_pointer(func, "view_layer", "ViewLayer", "", "");
- RNA_def_enum(func, "settings", calc_mode_items, 1, "", "Calculate density for rendering");
+ RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "");
/* TODO, See how array size of 0 works, this shouldnt be used. */
parm = RNA_def_float_array(func, "rgba_values", 1, NULL, 0, 0, "", "RGBA Values", 0, 0);
RNA_def_parameter_flags(parm, PROP_DYNAMIC, 0);
@@ -4219,9 +4233,7 @@ static void def_sh_tex_pointdensity(StructRNA *srna)
func = RNA_def_function(srna, "calc_point_density_minmax", "rna_ShaderNodePointDensity_density_minmax");
RNA_def_function_ui_description(func, "Calculate point density");
- RNA_def_pointer(func, "scene", "Scene", "", "");
- RNA_def_pointer(func, "view_layer", "ViewLayer", "", "");
- RNA_def_enum(func, "settings", calc_mode_items, 1, "", "Calculate density for rendering");
+ RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "");
parm = RNA_def_property(func, "min", PROP_FLOAT, PROP_COORDS);
RNA_def_property_array(parm, 3);
RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0);
@@ -4263,6 +4275,12 @@ static void def_principled(StructRNA *srna)
RNA_def_property_enum_items(prop, node_principled_distribution_items);
RNA_def_property_ui_text(prop, "Distribution", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodePrincipled_update");
+
+ prop = RNA_def_property(srna, "subsurface_method", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom2");
+ RNA_def_property_enum_items(prop, node_subsurface_method_items);
+ RNA_def_property_ui_text(prop, "Subsurface Method", "Method for rendering subsurface scattering");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodePrincipled_update");
}
static void def_refraction(StructRNA *srna)
@@ -4350,11 +4368,11 @@ static void def_sh_uvalongstroke(StructRNA *srna)
static void def_sh_normal_map(StructRNA *srna)
{
static const EnumPropertyItem prop_space_items[] = {
- {SHD_NORMAL_MAP_TANGENT, "TANGENT", 0, "Tangent Space", "Tangent space normal mapping"},
- {SHD_NORMAL_MAP_OBJECT, "OBJECT", 0, "Object Space", "Object space normal mapping"},
- {SHD_NORMAL_MAP_WORLD, "WORLD", 0, "World Space", "World space normal mapping"},
- {SHD_NORMAL_MAP_BLENDER_OBJECT, "BLENDER_OBJECT", 0, "Blender Object Space", "Object space normal mapping, compatible with Blender render baking"},
- {SHD_NORMAL_MAP_BLENDER_WORLD, "BLENDER_WORLD", 0, "Blender World Space", "World space normal mapping, compatible with Blender render baking"},
+ {SHD_SPACE_TANGENT, "TANGENT", 0, "Tangent Space", "Tangent space normal mapping"},
+ {SHD_SPACE_OBJECT, "OBJECT", 0, "Object Space", "Object space normal mapping"},
+ {SHD_SPACE_WORLD, "WORLD", 0, "World Space", "World space normal mapping"},
+ {SHD_SPACE_BLENDER_OBJECT, "BLENDER_OBJECT", 0, "Blender Object Space", "Object space normal mapping, compatible with Blender render baking"},
+ {SHD_SPACE_BLENDER_WORLD, "BLENDER_WORLD", 0, "Blender World Space", "World space normal mapping, compatible with Blender render baking"},
{0, NULL, 0, NULL, NULL}
};
@@ -4374,6 +4392,45 @@ static void def_sh_normal_map(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "bNode", NULL);
}
+static void def_sh_displacement(StructRNA *srna)
+{
+ static const EnumPropertyItem prop_space_items[] = {
+ {SHD_SPACE_OBJECT, "OBJECT", 0, "Object Space", "Displacement is in object space, affected by object scale"},
+ {SHD_SPACE_WORLD, "WORLD", 0, "World Space", "Displacement is in world space, not affected by object scale"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_enum_items(prop, prop_space_items);
+ RNA_def_property_ui_text(prop, "Space", "Space of the input height");
+ RNA_def_property_update(prop, 0, "rna_Node_update");
+
+ RNA_def_struct_sdna_from(srna, "bNode", NULL);
+}
+
+static void def_sh_vector_displacement(StructRNA *srna)
+{
+ static const EnumPropertyItem prop_space_items[] = {
+ {SHD_SPACE_TANGENT, "TANGENT", 0, "Tangent Space", "Tagent space vector displacement mapping"},
+ {SHD_SPACE_OBJECT, "OBJECT", 0, "Object Space", "Object space vector displacement mapping"},
+ {SHD_SPACE_WORLD, "WORLD", 0, "World Space", "World space vector displacement mapping"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_enum_items(prop, prop_space_items);
+ RNA_def_property_ui_text(prop, "Space", "Space of the input height");
+ RNA_def_property_update(prop, 0, "rna_Node_update");
+
+ RNA_def_struct_sdna_from(srna, "bNode", NULL);
+}
+
static void def_sh_tangent(StructRNA *srna)
{
static const EnumPropertyItem prop_direction_type_items[] = {
@@ -4427,6 +4484,7 @@ static void def_sh_subsurface(StructRNA *srna)
{SHD_SUBSURFACE_CUBIC, "CUBIC", 0, "Cubic", "Simple cubic falloff function"},
{SHD_SUBSURFACE_GAUSSIAN, "GAUSSIAN", 0, "Gaussian", "Normal distribution, multiple can be combined to fit more complex profiles"},
{SHD_SUBSURFACE_BURLEY, "BURLEY", 0, "Christensen-Burley", "Approximation to physically based volume scattering"},
+ {SHD_SUBSURFACE_RANDOM_WALK, "RANDOM_WALK", 0, "Random Walk", "Volumetric approximation to physically based volume scattering"},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index bba415f184b..43001d6bd66 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -33,17 +33,19 @@
#include "DNA_group_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
#include "DNA_property_types.h"
#include "DNA_scene_types.h"
#include "DNA_meta_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BKE_camera.h"
#include "BKE_paint.h"
+#include "BKE_editlattice.h"
#include "BKE_editmesh.h"
#include "BKE_group.h" /* needed for BKE_group_object_exists() */
#include "BKE_object_deform.h"
@@ -218,6 +220,12 @@ static void rna_Object_internal_update(Main *UNUSED(bmain), Scene *UNUSED(scene)
DEG_id_tag_update(ptr->id.data, OB_RECALC_OB);
}
+static void rna_Object_internal_update_draw(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_OB);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ptr->id.data);
+}
+
static void rna_Object_matrix_world_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
/* don't use compat so we get predictable rotation */
@@ -295,16 +303,18 @@ void rna_Object_internal_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene),
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ptr->id.data);
}
-static void rna_Object_active_shape_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Object_active_shape_update(bContext *C, PointerRNA *ptr)
{
Object *ob = ptr->id.data;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
- if (scene->obedit == ob) {
+ if (CTX_data_edit_object(C) == ob) {
/* exit/enter editmode to get new shape */
switch (ob->type) {
case OB_MESH:
EDBM_mesh_load(ob);
- EDBM_mesh_make(scene->toolsettings, ob, true);
+ EDBM_mesh_make(ob, scene->toolsettings->selectmode, true);
DEG_id_tag_update(ob->data, 0);
@@ -317,8 +327,8 @@ static void rna_Object_active_shape_update(Main *bmain, Scene *scene, PointerRNA
ED_curve_editnurb_make(ob);
break;
case OB_LATTICE:
- ED_lattice_editlatt_load(ob);
- ED_lattice_editlatt_make(ob);
+ BKE_editlattice_load(ob);
+ BKE_editlattice_make(ob);
break;
}
}
@@ -2756,7 +2766,7 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "index");
RNA_def_property_ui_text(prop, "Pass Index", "Index number for the \"Object Index\" render pass");
- RNA_def_property_update(prop, NC_OBJECT, "rna_Object_internal_update");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_Object_internal_update_draw");
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "col");
@@ -2831,6 +2841,7 @@ static void rna_def_object(BlenderRNA *brna)
NULL,
NULL);
RNA_def_property_struct_type(prop, "LayerCollectionSettings");
+ RNA_def_property_flag(prop, PROP_NO_COMPARISON); /* XXX see T53800. */
RNA_def_property_ui_text(prop, "Collection Settings",
"Engine specific render settings to be overridden by collections");
@@ -2918,11 +2929,6 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Dupli Frames Off", "Recurring frames to exclude from the Dupliframes");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update");
- prop = RNA_def_property(srna, "dupli_list", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "duplilist", NULL);
- RNA_def_property_struct_type(prop, "DupliObject");
- RNA_def_property_ui_text(prop, "Dupli list", "Object duplis");
-
prop = RNA_def_property(srna, "is_duplicator", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "transflag", OB_DUPLI);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -3023,6 +3029,7 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "active_shape_key_index", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "shapenr");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* XXX this is really unpredictable... */
RNA_def_property_int_funcs(prop, "rna_Object_active_shape_key_index_get", "rna_Object_active_shape_key_index_set",
"rna_Object_active_shape_key_index_range");
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 74528a2c0e8..3b934b10d64 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -148,7 +148,7 @@ static int rna_Object_visible_get(Object *ob, bContext *C, ReportList *reports)
}
/* Convert a given matrix from a space to another (using the object and/or a bone as reference). */
-static void rna_Scene_mat_convert_space(Object *ob, ReportList *reports, bPoseChannel *pchan,
+static void rna_Object_mat_convert_space(Object *ob, ReportList *reports, bPoseChannel *pchan,
float *mat, float *mat_ret, int from, int to)
{
copy_m4_m4((float (*)[4])mat_ret, (float (*)[4])mat);
@@ -197,94 +197,12 @@ static void rna_Object_camera_fit_coords(
/* copied from Mesh_getFromObject and adapted to RNA interface */
/* settings: 0 - preview, 1 - render */
static Mesh *rna_Object_to_mesh(
- Object *ob, bContext *C, ReportList *reports, Scene *sce, ViewLayer *view_layer,
- int apply_modifiers, int settings, int calc_tessface, int calc_undeformed)
+ Object *ob, bContext *C, ReportList *reports, Depsgraph *depsgraph,
+ int apply_modifiers, int calc_tessface, int calc_undeformed)
{
Main *bmain = CTX_data_main(C);
- return rna_Main_meshes_new_from_object(bmain, reports, sce, view_layer, ob, apply_modifiers, settings, calc_tessface, calc_undeformed);
-}
-
-/* mostly a copy from convertblender.c */
-static void dupli_render_particle_set(EvaluationContext *eval_ctx, Scene *scene, Object *ob, int level, int enable)
-{
- /* ugly function, but we need to set particle systems to their render
- * settings before calling object_duplilist, to get render level duplis */
- Group *group;
- GroupObject *go;
- ParticleSystem *psys;
- DerivedMesh *dm;
- float mat[4][4];
-
- unit_m4(mat);
-
- if (level >= MAX_DUPLI_RECUR)
- return;
-
- if (ob->transflag & OB_DUPLIPARTS) {
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (ELEM(psys->part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
- if (enable)
- psys_render_set(ob, psys, mat, mat, 1, 1, 0.f);
- else
- psys_render_restore(ob, psys);
- }
- }
-
- if (enable) {
- /* this is to make sure we get render level duplis in groups:
- * the derivedmesh must be created before init_render_mesh,
- * since object_duplilist does dupliparticles before that */
- dm = mesh_create_derived_render(eval_ctx, scene, ob, CD_MASK_BAREMESH | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL);
- dm->release(dm);
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next)
- psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated;
- }
- }
-
- if (ob->dup_group == NULL) return;
- group = ob->dup_group;
-
- for (go = group->gobject.first; go; go = go->next)
- dupli_render_particle_set(eval_ctx, scene, go->ob, level + 1, enable);
-}
-/* When no longer needed, duplilist should be freed with Object.free_duplilist */
-static void rna_Object_create_duplilist(Object *ob, bContext *C, ReportList *reports, Scene *sce, int settings)
-{
- bool for_render = (settings == DAG_EVAL_RENDER);
- EvaluationContext eval_ctx;
-
- CTX_data_eval_ctx(C, &eval_ctx);
-
- eval_ctx.mode = settings;
-
- if (!(ob->transflag & OB_DUPLI)) {
- BKE_report(reports, RPT_ERROR, "Object does not have duplis");
- return;
- }
-
- /* free duplilist if a user forgets to */
- if (ob->duplilist) {
- BKE_report(reports, RPT_WARNING, "Object.dupli_list has not been freed");
-
- free_object_duplilist(ob->duplilist);
- ob->duplilist = NULL;
- }
- if (for_render)
- dupli_render_particle_set(&eval_ctx, sce, ob, 0, 1);
- ob->duplilist = object_duplilist(&eval_ctx, sce, ob);
- if (for_render)
- dupli_render_particle_set(&eval_ctx, sce, ob, 0, 0);
- /* ob->duplilist should now be freed with Object.free_duplilist */
-}
-
-static void rna_Object_free_duplilist(Object *ob)
-{
- if (ob->duplilist) {
- free_object_duplilist(ob->duplilist);
- ob->duplilist = NULL;
- }
+ return rna_Main_meshes_new_from_object(bmain, reports, depsgraph, ob, apply_modifiers, calc_tessface, calc_undeformed);
}
static PointerRNA rna_Object_shape_key_add(Object *ob, bContext *C, ReportList *reports,
@@ -526,10 +444,8 @@ void rna_Object_dm_info(struct Object *ob, int type, char *result)
static int rna_Object_update_from_editmode(Object *ob)
{
- if (ob->mode & OB_MODE_EDIT) {
- return ED_object_editmode_load(ob);
- }
- return false;
+ /* fail gracefully if we aren't in edit-mode. */
+ return ED_object_editmode_load(ob);
}
#else /* RNA_RUNTIME */
@@ -544,13 +460,6 @@ void RNA_api_object(StructRNA *srna)
{0, NULL, 0, NULL, NULL}
};
- static const EnumPropertyItem dupli_eval_mode_items[] = {
- {DAG_EVAL_VIEWPORT, "VIEWPORT", 0, "Viewport", "Generate duplis using viewport settings"},
- {DAG_EVAL_PREVIEW, "PREVIEW", 0, "Preview", "Generate duplis using preview settings"},
- {DAG_EVAL_RENDER, "RENDER", 0, "Render", "Generate duplis using render settings"},
- {0, NULL, 0, NULL, NULL}
- };
-
#ifndef NDEBUG
static const EnumPropertyItem mesh_dm_info_items[] = {
{0, "SOURCE", 0, "Source", "Source mesh"},
@@ -587,7 +496,7 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_return(func, parm);
/* Matrix space conversion */
- func = RNA_def_function(srna, "convert_space", "rna_Scene_mat_convert_space");
+ func = RNA_def_function(srna, "convert_space", "rna_Object_mat_convert_space");
RNA_def_function_ui_description(func, "Convert (transform) the given matrix from one space to another");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "pose_bone", "PoseBone", "",
@@ -638,33 +547,16 @@ void RNA_api_object(StructRNA *srna)
func = RNA_def_function(srna, "to_mesh", "rna_Object_to_mesh");
RNA_def_function_ui_description(func, "Create a Mesh data-block with modifiers applied");
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_CONTEXT);
- parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene within which to evaluate modifiers");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
- parm = RNA_def_pointer(func, "view_layer", "ViewLayer", "", "Scene layer within which to evaluate modifiers");
+ parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "Dependency Graph", "Evaluated dependency graph within wich to evaluate modifiers");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
parm = RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- parm = RNA_def_enum(func, "settings", mesh_type_items, 0, "", "Modifier settings to apply");
- RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
RNA_def_boolean(func, "calc_tessface", true, "Calculate Tessellation", "Calculate tessellation faces");
RNA_def_boolean(func, "calc_undeformed", false, "Calculate Undeformed", "Calculate undeformed vertex coordinates");
parm = RNA_def_pointer(func, "mesh", "Mesh", "",
"Mesh created from object, remove it if it is only used for export");
RNA_def_function_return(func, parm);
- /* duplis */
- func = RNA_def_function(srna, "dupli_list_create", "rna_Object_create_duplilist");
- RNA_def_function_ui_description(func, "Create a list of dupli objects for this object, needs to "
- "be freed manually with free_dupli_list to restore the "
- "objects real matrix and layers");
- parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene within which to evaluate duplis");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
- RNA_def_enum(func, "settings", dupli_eval_mode_items, 0, "", "Generate texture coordinates for rendering");
- RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_CONTEXT);
-
- func = RNA_def_function(srna, "dupli_list_clear", "rna_Object_free_duplilist");
- RNA_def_function_ui_description(func, "Free the list of dupli objects");
-
/* Armature */
func = RNA_def_function(srna, "find_armature", "modifiers_isDeformedByArmature");
RNA_def_function_ui_description(func, "Find armature influencing this object as a parent or via a modifier");
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 9265c7b62cf..7d062d41e4f 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -28,7 +28,7 @@
#include "DNA_cloth_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_smoke_types.h"
@@ -108,65 +108,45 @@ static void rna_Cache_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
{
Object *ob = (Object *)ptr->id.data;
PointCache *cache = (PointCache *)ptr->data;
- PTCacheID *pid = NULL;
- ListBase pidlist;
if (!ob)
return;
cache->flag |= PTCACHE_OUTDATED;
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
+ PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache)
- break;
- }
-
- if (pid) {
+ if (pid.cache) {
/* Just make sure this wasn't changed. */
- if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN)
+ if (pid.type == PTCACHE_TYPE_SMOKE_DOMAIN)
cache->step = 1;
- BKE_ptcache_update_info(pid);
+ BKE_ptcache_update_info(&pid);
}
-
- BLI_freelistN(&pidlist);
}
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;
- PTCacheID *pid = NULL;
- ListBase pidlist;
if (!ob)
return;
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
-
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache)
- break;
- }
+ PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
/* smoke can only use disk cache */
- if (pid && pid->type != PTCACHE_TYPE_SMOKE_DOMAIN)
- BKE_ptcache_toggle_disk_cache(pid);
+ if (pid.cache && pid.type != PTCACHE_TYPE_SMOKE_DOMAIN)
+ BKE_ptcache_toggle_disk_cache(&pid);
else
cache->flag ^= PTCACHE_DISK_CACHE;
-
- BLI_freelistN(&pidlist);
}
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;
- PTCacheID *pid = NULL, *pid2 = NULL;
- ListBase pidlist;
bool use_new_name = true;
if (!ob)
@@ -174,23 +154,22 @@ static void rna_Cache_idname_change(Main *UNUSED(bmain), Scene *UNUSED(scene), P
/* TODO: check for proper characters */
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
-
if (cache->flag & PTCACHE_EXTERNAL) {
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache)
- break;
- }
-
- if (!pid)
- return;
+ PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
- BKE_ptcache_load_external(pid);
+ if (pid.cache) {
+ BKE_ptcache_load_external(&pid);
+ }
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, ob);
}
else {
+ PTCacheID *pid = NULL, *pid2 = NULL;
+ ListBase pidlist;
+
+ BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
+
for (pid = pidlist.first; pid; pid = pid->next) {
if (pid->cache == cache)
pid2 = pid;
@@ -216,9 +195,9 @@ static void rna_Cache_idname_change(Main *UNUSED(bmain), Scene *UNUSED(scene), P
BLI_strncpy(cache->prev_name, cache->name, sizeof(cache->prev_name));
}
- }
- BLI_freelistN(&pidlist);
+ BLI_freelistN(&pidlist);
+ }
}
static void rna_Cache_list_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
@@ -239,43 +218,27 @@ static void rna_Cache_active_point_cache_index_range(PointerRNA *ptr, int *min,
{
Object *ob = ptr->id.data;
PointCache *cache = ptr->data;
- PTCacheID *pid;
- ListBase pidlist;
-
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
+ PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
*min = 0;
*max = 0;
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache) {
- *max = max_ii(0, BLI_listbase_count(pid->ptcaches) - 1);
- break;
- }
+ if (pid.cache) {
+ *max = max_ii(0, BLI_listbase_count(pid.ptcaches) - 1);
}
-
- BLI_freelistN(&pidlist);
}
static int rna_Cache_active_point_cache_index_get(PointerRNA *ptr)
{
Object *ob = ptr->id.data;
PointCache *cache = ptr->data;
- PTCacheID *pid;
- ListBase pidlist;
+ PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
int num = 0;
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
-
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache) {
- num = BLI_findindex(pid->ptcaches, cache);
- break;
- }
+ if (pid.cache) {
+ num = BLI_findindex(pid.ptcaches, cache);
}
- BLI_freelistN(&pidlist);
-
return num;
}
@@ -283,19 +246,11 @@ static void rna_Cache_active_point_cache_index_set(struct PointerRNA *ptr, int v
{
Object *ob = ptr->id.data;
PointCache *cache = ptr->data;
- PTCacheID *pid;
- ListBase pidlist;
-
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
+ PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache) {
- *(pid->cache_ptr) = BLI_findlink(pid->ptcaches, value);
- break;
- }
+ if (pid.cache) {
+ *(pid.cache_ptr) = BLI_findlink(pid.ptcaches, value);
}
-
- BLI_freelistN(&pidlist);
}
static void rna_PointCache_frame_step_range(PointerRNA *ptr, int *min, int *max,
@@ -303,22 +258,14 @@ static void rna_PointCache_frame_step_range(PointerRNA *ptr, int *min, int *max,
{
Object *ob = ptr->id.data;
PointCache *cache = ptr->data;
- PTCacheID *pid;
- ListBase pidlist;
+ PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
*min = 1;
*max = 20;
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
-
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache) {
- *max = pid->max_step;
- break;
- }
+ if (pid.cache) {
+ *max = pid.max_step;
}
-
- BLI_freelistN(&pidlist);
}
static char *rna_CollisionSettings_path(PointerRNA *UNUSED(ptr))
@@ -608,11 +555,11 @@ static void rna_EffectorWeight_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
if (id && GS(id->name) == ID_SCE) {
Scene *scene = (Scene *)id;
- FOREACH_SCENE_OBJECT(scene, ob)
+ FOREACH_SCENE_OBJECT_BEGIN(scene, ob)
{
BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH);
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
}
else {
DEG_id_tag_update(id, OB_RECALC_DATA | PSYS_RECALC_RESET);
@@ -771,31 +718,8 @@ static const EnumPropertyItem *rna_Effector_shape_itemf(bContext *UNUSED(C), Poi
#else
-/* ptcache.point_caches */
-static void rna_def_ptcache_point_caches(BlenderRNA *brna, PropertyRNA *cprop)
+static void rna_def_pointcache_common(StructRNA *srna)
{
- StructRNA *srna;
- PropertyRNA *prop;
-
- /* FunctionRNA *func; */
- /* PropertyRNA *parm; */
-
- RNA_def_property_srna(cprop, "PointCaches");
- srna = RNA_def_struct(brna, "PointCaches", NULL);
- RNA_def_struct_sdna(srna, "PointCache");
- RNA_def_struct_ui_text(srna, "Point Caches", "Collection of point caches");
-
- prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop, "rna_Cache_active_point_cache_index_get",
- "rna_Cache_active_point_cache_index_set",
- "rna_Cache_active_point_cache_index_range");
- RNA_def_property_ui_text(prop, "Active Point Cache Index", "");
- RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
-}
-
-static void rna_def_pointcache(BlenderRNA *brna)
-{
- StructRNA *srna;
PropertyRNA *prop;
static const EnumPropertyItem point_cache_compress_items[] = {
@@ -805,16 +729,12 @@ static void rna_def_pointcache(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- srna = RNA_def_struct(brna, "PointCache", NULL);
- RNA_def_struct_ui_text(srna, "Point Cache", "Point cache for physics simulations");
- RNA_def_struct_ui_icon(srna, ICON_PHYSICS);
-
prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "startframe");
RNA_def_property_range(prop, -MAXFRAME, MAXFRAME);
RNA_def_property_ui_range(prop, 1, MAXFRAME, 1, 1);
RNA_def_property_ui_text(prop, "Start", "Frame on which the simulation starts");
-
+
prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "endframe");
RNA_def_property_range(prop, 1, MAXFRAME);
@@ -895,13 +815,59 @@ static void rna_def_pointcache(BlenderRNA *brna)
"Use this file's path for the disk cache when library linked into another file "
"(for local bakes per scene file, disable this option)");
RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
+}
+
+static void rna_def_ptcache_point_caches(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ /* FunctionRNA *func; */
+ /* PropertyRNA *parm; */
+
+ RNA_def_property_srna(cprop, "PointCaches");
+ srna = RNA_def_struct(brna, "PointCaches", NULL);
+ RNA_def_struct_sdna(srna, "PointCache");
+ RNA_def_struct_ui_text(srna, "Point Caches", "Collection of point caches");
+
+ prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_funcs(prop, "rna_Cache_active_point_cache_index_get",
+ "rna_Cache_active_point_cache_index_set",
+ "rna_Cache_active_point_cache_index_range");
+ RNA_def_property_ui_text(prop, "Active Point Cache Index", "");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
+
+ /* And define another RNA type for those collection items. */
+ srna = RNA_def_struct(brna, "PointCacheItem", NULL);
+ RNA_def_struct_sdna(srna, "PointCache");
+ RNA_def_struct_ui_text(srna, "Point Cache", "point cache for physics simulations");
+ RNA_def_struct_ui_icon(srna, ICON_PHYSICS);
+
+ rna_def_pointcache_common(srna);
+}
+
+static void rna_def_pointcache_active(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "PointCache", NULL);
+ RNA_def_struct_ui_text(srna, "Active Point Cache", "Active point cache for physics simulations");
+ RNA_def_struct_ui_icon(srna, ICON_PHYSICS);
+
+ rna_def_pointcache_common(srna);
+ /* This first-level RNA pointer also has list of all caches from owning ID.
+ * Those caches items have exact same content as 'active' one, except for that collection,
+ * to prevent ugly recursive layout pattern.
+ * Note: This shall probably be redone from scratch in a proper way at some poitn, but for now that will do,
+ * and shall not break anything in the API. */
prop = RNA_def_property(srna, "point_caches", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_funcs(prop, "rna_Cache_list_begin", "rna_iterator_listbase_next",
"rna_iterator_listbase_end", "rna_iterator_listbase_get",
NULL, NULL, NULL, NULL);
- RNA_def_property_struct_type(prop, "PointCache");
- RNA_def_property_ui_text(prop, "Point Cache List", "Point cache list");
+ RNA_def_property_struct_type(prop, "PointCacheItem");
+ RNA_def_property_ui_text(prop, "Point Cache List", "");
rna_def_ptcache_point_caches(brna, prop);
}
@@ -1881,7 +1847,7 @@ static void rna_def_softbody(BlenderRNA *brna)
void RNA_def_object_force(BlenderRNA *brna)
{
- rna_def_pointcache(brna);
+ rna_def_pointcache_active(brna);
rna_def_collision(brna);
rna_def_effector_weight(brna);
rna_def_field(brna);
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 12e56b8e926..f0d5a7e7c2e 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -36,7 +36,7 @@
#include "DNA_modifier_types.h"
#include "DNA_cloth_types.h"
#include "DNA_particle_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_boid_types.h"
@@ -325,27 +325,18 @@ static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *o
ParticleData *pars = NULL;
ParticleCacheKey *cache = NULL;
int totchild = 0;
- int path_nbr = 0;
int totpart;
int max_k = 0;
- int step_nbr = 0;
if (particlesystem == NULL)
return;
part = particlesystem->part;
pars = particlesystem->particles;
+ totpart = particlesystem->totcached;
+ totchild = particlesystem->totchildcache;
- if (particlesystem->renderdata) {
- step_nbr = part->ren_step;
- totchild = particlesystem->totchild;
- }
- else {
- step_nbr = part->draw_step;
- totchild = (int)((float)particlesystem->totchild * (float)(part->disp) / 100.0f);
- }
-
- if (part == NULL || pars == NULL || !psys_check_enabled(object, particlesystem, particlesystem->renderdata != NULL))
+ if (part == NULL || pars == NULL)
return;
if (part->ren_as == PART_DRAW_OB || part->ren_as == PART_DRAW_GR || part->ren_as == PART_DRAW_NOT)
@@ -355,47 +346,28 @@ static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *o
if (part->type == PART_HAIR && !particlesystem->childcache)
totchild = 0;
- totpart = particlesystem->totpart;
-
- if (particle_no >= totpart + totchild)
- return;
-
- if (part->ren_as == PART_DRAW_PATH && particlesystem->pathcache)
- path_nbr = 1 << step_nbr;
- if (part->kink == PART_KINK_SPIRAL)
- path_nbr += part->kink_extra_steps;
-
if (particle_no < totpart) {
+ cache = particlesystem->pathcache[particle_no];
+ max_k = (int)cache->segments;
+ }
+ else if (particle_no < totpart + totchild) {
+ cache = particlesystem->childcache[particle_no - totpart];
- if (path_nbr) {
- cache = particlesystem->pathcache[particle_no];
+ if (cache->segments < 0)
+ max_k = 0;
+ else
max_k = (int)cache->segments;
- }
-
}
else {
-
- if (path_nbr) {
- cache = particlesystem->childcache[particle_no - totpart];
-
- if (cache->segments < 0)
- max_k = 0;
- else
- max_k = (int)cache->segments;
- }
+ return;
}
- /*strands key loop data stored in cache + step->co*/
- if (path_nbr) {
- if (step >= 0 && step <= path_nbr) {
- if (step <= max_k) {
- copy_v3_v3(n_co, (cache + step)->co);
- mul_m4_v3(particlesystem->imat, n_co);
- mul_m4_v3(object->obmat, n_co);
- }
- }
+ /* Strands key loop data stored in cache + step->co. */
+ if (step >= 0 && step <= max_k) {
+ copy_v3_v3(n_co, (cache + step)->co);
+ mul_m4_v3(particlesystem->imat, n_co);
+ mul_m4_v3(object->obmat, n_co);
}
-
}
@@ -461,20 +433,13 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys
}
part = particlesystem->part;
-
- if (particlesystem->renderdata) {
- totchild = particlesystem->totchild;
- }
- else {
- totchild = (int)((float)particlesystem->totchild * (float)(part->disp) / 100.0f);
- }
+ totpart = particlesystem->totcached;
+ totchild = particlesystem->totchildcache;
/* can happen for disconnected/global hair */
if (part->type == PART_HAIR && !particlesystem->childcache)
totchild = 0;
- totpart = particlesystem->totpart;
-
if (particle_no >= totpart + totchild)
return num;
@@ -614,36 +579,6 @@ static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem, R
}
}
-static void rna_ParticleSystem_set_resolution(ParticleSystem *particlesystem, Scene *scene, ViewLayer *view_layer, Object *object, int resolution)
-{
- EvaluationContext eval_ctx;
-
- DEG_evaluation_context_init(&eval_ctx, resolution);
- eval_ctx.ctime = (float)scene->r.cfra + scene->r.subframe;
- eval_ctx.view_layer = view_layer;
-
- if (resolution == eModifierMode_Render) {
- ParticleSystemModifierData *psmd = psys_get_modifier(object, particlesystem);
- float mat[4][4];
-
- unit_m4(mat);
-
- psys_render_set(object, particlesystem, mat, mat, 1, 1, 0.f);
- psmd->flag &= ~eParticleSystemFlag_psys_updated;
- particle_system_update(&eval_ctx, scene, object, particlesystem, true);
- }
- else {
- ParticleSystemModifierData *psmd = psys_get_modifier(object, particlesystem);
-
- if (particlesystem->renderdata) {
- psys_render_restore(object, particlesystem);
- }
-
- psmd->flag &= ~eParticleSystemFlag_psys_updated;
- particle_system_update(&eval_ctx, scene, object, particlesystem, false);
- }
-}
-
static void particle_recalc(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr, short flag)
{
if (ptr->type == &RNA_ParticleSystem) {
@@ -953,6 +888,19 @@ static void rna_ParticleSettings_use_roughness_curve_update(Main *bmain, Scene *
rna_Particle_redo_child(bmain, scene, ptr);
}
+static void rna_ParticleSettings_use_twist_curve_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ ParticleSettings *part = ptr->data;
+
+ if (part->child_flag & PART_CHILD_USE_TWIST_CURVE) {
+ if (!part->twistcurve) {
+ BKE_particlesettings_twist_curve_init(part);
+ }
+ }
+
+ rna_Particle_redo_child(bmain, scene, ptr);
+}
+
static void rna_ParticleSystem_name_set(PointerRNA *ptr, const char *value)
{
Object *ob = ptr->id.data;
@@ -1309,6 +1257,7 @@ static void rna_ParticleVGroup_name_get_8(PointerRNA *ptr, char *value) { psys_v
static void rna_ParticleVGroup_name_get_9(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 9); }
static void rna_ParticleVGroup_name_get_10(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 10); }
static void rna_ParticleVGroup_name_get_11(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 11); }
+static void rna_ParticleVGroup_name_get_12(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 12); }
static int rna_ParticleVGroup_name_len_0(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 0); }
static int rna_ParticleVGroup_name_len_1(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 1); }
@@ -1322,6 +1271,7 @@ static int rna_ParticleVGroup_name_len_8(PointerRNA *ptr) { return psys_vg_name_
static int rna_ParticleVGroup_name_len_9(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 9); }
static int rna_ParticleVGroup_name_len_10(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 10); }
static int rna_ParticleVGroup_name_len_11(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 11); }
+static int rna_ParticleVGroup_name_len_12(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 12); }
static void rna_ParticleVGroup_name_set_0(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 0); }
static void rna_ParticleVGroup_name_set_1(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 1); }
@@ -1335,6 +1285,7 @@ static void rna_ParticleVGroup_name_set_8(PointerRNA *ptr, const char *value) {
static void rna_ParticleVGroup_name_set_9(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 9); }
static void rna_ParticleVGroup_name_set_10(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 10); }
static void rna_ParticleVGroup_name_set_11(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 11); }
+static void rna_ParticleVGroup_name_set_12(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 12); }
#else
@@ -1887,6 +1838,10 @@ static void rna_def_particle_settings_mtex(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Length", "Affect the child hair length");
RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+ prop = RNA_def_property(srna, "use_map_twist", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_TWIST);
+ RNA_def_property_ui_text(prop, "Twist", "Affect the child twist");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
/* influence factors */
prop = RNA_def_property(srna, "time_factor", PROP_FLOAT, PROP_NONE);
@@ -1968,6 +1923,12 @@ static void rna_def_particle_settings_mtex(BlenderRNA *brna)
RNA_def_property_ui_range(prop, 0, 1, 10, 3);
RNA_def_property_ui_text(prop, "Rough Factor", "Amount texture affects child roughness");
RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+
+ prop = RNA_def_property(srna, "twist_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "twistfac");
+ RNA_def_property_ui_range(prop, 0, 1, 10, 3);
+ RNA_def_property_ui_text(prop, "Twist Factor", "Amount texture affects child twist");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
}
static void rna_def_particle_settings(BlenderRNA *brna)
@@ -2382,7 +2343,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "draw_size", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0, 1000);
RNA_def_property_ui_range(prop, 0, 100, 1, -1);
- RNA_def_property_ui_text(prop, "Draw Size", "Size of particles on viewport in BU (0.1 = default)");
+ RNA_def_property_ui_text(prop, "Draw Size", "Size of particles on viewport in BU");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
prop = RNA_def_property(srna, "child_type", PROP_ENUM, PROP_NONE);
@@ -2540,33 +2501,6 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Billboard Velocity Tail", "Scale billboards by velocity");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
- /* simplification */
- prop = RNA_def_property(srna, "use_simplify", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "simplify_flag", PART_SIMPLIFY_ENABLE);
- RNA_def_property_ui_text(prop, "Child Simplification",
- "Remove child strands as the object becomes smaller on the screen");
-
- prop = RNA_def_property(srna, "use_simplify_viewport", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "simplify_flag", PART_SIMPLIFY_VIEWPORT);
- RNA_def_property_ui_text(prop, "Viewport", "");
-
- prop = RNA_def_property(srna, "simplify_refsize", PROP_INT, PROP_PIXEL);
- RNA_def_property_int_sdna(prop, NULL, "simplify_refsize");
- RNA_def_property_range(prop, 1, SHRT_MAX);
- RNA_def_property_ui_text(prop, "Reference Size", "Reference size in pixels, after which simplification begins");
-
- prop = RNA_def_property(srna, "simplify_rate", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Rate", "Speed of simplification");
-
- prop = RNA_def_property(srna, "simplify_transition", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Transition", "Transition period for fading out strands");
-
- prop = RNA_def_property(srna, "simplify_viewport", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 0.999f);
- RNA_def_property_ui_text(prop, "Rate", "Speed of Simplification");
-
/* general values */
prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "sta"); /*optional if prop names are the same */
@@ -3174,6 +3108,25 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "FieldSettings");
RNA_def_property_pointer_funcs(prop, "rna_Particle_field2_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Force Field 2", "");
+
+ /* twist */
+ prop = RNA_def_property(srna, "twist", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, -100000.0f, 100000.0f);
+ RNA_def_property_ui_range(prop, -10.0f, 10.0f, 0.1, 3);
+ RNA_def_property_ui_text(prop, "Twist", "Number of turns around parent allong the strand");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+
+ prop = RNA_def_property(srna, "use_twist_curve", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "child_flag", PART_CHILD_USE_TWIST_CURVE);
+ RNA_def_property_ui_text(prop, "Use Twist Curve", "Use a curve to define twist");
+ RNA_def_property_update(prop, 0, "rna_ParticleSettings_use_twist_curve_update");
+
+ prop = RNA_def_property(srna, "twist_curve", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "twistcurve");
+ RNA_def_property_struct_type(prop, "CurveMapping");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Twist Curve", "Curve defining twist");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
}
static void rna_def_particle_target(BlenderRNA *brna)
@@ -3244,12 +3197,6 @@ static void rna_def_particle_system(BlenderRNA *brna)
FunctionRNA *func;
PropertyRNA *parm;
- static const EnumPropertyItem resolution_items[] = {
- {eModifierMode_Realtime, "PREVIEW", 0, "Preview", "Apply modifier preview settings"},
- {eModifierMode_Render, "RENDER", 0, "Render", "Apply modifier render settings"},
- {0, NULL, 0, NULL, NULL}
- };
-
srna = RNA_def_struct(brna, "ParticleSystem", NULL);
RNA_def_struct_ui_text(srna, "Particle System", "Particle system in an object");
RNA_def_struct_ui_icon(srna, ICON_PARTICLE_DATA);
@@ -3273,11 +3220,13 @@ static void rna_def_particle_system(BlenderRNA *brna)
prop = RNA_def_property(srna, "particles", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "particles", "totpart");
RNA_def_property_struct_type(prop, "Particle");
+ RNA_def_property_flag(prop, PROP_NO_COMPARISON);
RNA_def_property_ui_text(prop, "Particles", "Particles generated by the particle system");
prop = RNA_def_property(srna, "child_particles", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "child", "totchild");
RNA_def_property_struct_type(prop, "ChildParticle");
+ RNA_def_property_flag(prop, PROP_NO_COMPARISON);
RNA_def_property_ui_text(prop, "Child Particles", "Child particles generated by the particle system");
prop = RNA_def_property(srna, "seed", PROP_INT, PROP_UNSIGNED);
@@ -3507,6 +3456,18 @@ static void rna_def_particle_system(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Vertex Group Field Negate", "Negate the effect of the field vertex group");
RNA_def_property_update(prop, 0, "rna_Particle_reset");
+ prop = RNA_def_property(srna, "vertex_group_twist", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, "rna_ParticleVGroup_name_get_12", "rna_ParticleVGroup_name_len_12",
+ "rna_ParticleVGroup_name_set_12");
+ RNA_def_property_ui_text(prop, "Vertex Group Twist", "Vertex group to control twist");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+
+ prop = RNA_def_property(srna, "invert_vertex_group_twist", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "vg_neg", (1 << PSYS_VG_TWIST));
+ RNA_def_property_ui_text(prop, "Vertex Group Twist Negate",
+ "Negate the effect of the twist vertex group");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+
/* pointcache */
prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
@@ -3548,14 +3509,6 @@ static void rna_def_particle_system(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_ParticleSystem_path");
- /* set viewport or render resolution */
- func = RNA_def_function(srna, "set_resolution", "rna_ParticleSystem_set_resolution");
- RNA_def_function_ui_description(func, "Set the resolution to use for the number of particles");
- RNA_def_pointer(func, "scene", "Scene", "", "Scene");
- RNA_def_pointer(func, "view_layer", "ViewLayer", "", "ViewLayer");
- RNA_def_pointer(func, "object", "Object", "", "Object");
- RNA_def_enum(func, "resolution", resolution_items, 0, "", "Resolution settings to apply");
-
/* extract cached hair location data */
func = RNA_def_function(srna, "co_hair", "rna_ParticleSystem_co_hair");
RNA_def_function_ui_description(func, "Obtain cache hair data");
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 15487082217..ae774f8d41a 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -91,6 +91,7 @@ const EnumPropertyItem rna_enum_bake_pass_type_items[] = {
{SCE_PASS_SHADOW, "SHADOW", 0, "Shadow", ""},
{SCE_PASS_NORMAL, "NORMAL", 0, "Normal", ""},
{SCE_PASS_UV, "UV", 0, "UV", ""},
+ {SCE_PASS_ROUGHNESS, "ROUGHNESS", 0, "ROUGHNESS", ""},
{SCE_PASS_EMIT, "EMIT", 0, "Emit", ""},
{SCE_PASS_ENVIRONMENT, "ENVIRONMENT", 0, "Environment", ""},
{SCE_PASS_DIFFUSE_COLOR, "DIFFUSE", 0, "Diffuse", ""},
@@ -147,7 +148,7 @@ static void engine_unbind_display_space_shader(RenderEngine *UNUSED(engine))
IMB_colormanagement_finish_glsl_draw();
}
-static void engine_update(RenderEngine *engine, Main *bmain, Depsgraph *graph, Scene *scene)
+static void engine_update(RenderEngine *engine, Main *bmain, Scene *scene)
{
extern FunctionRNA rna_RenderEngine_update_func;
PointerRNA ptr;
@@ -159,14 +160,13 @@ static void engine_update(RenderEngine *engine, Main *bmain, Depsgraph *graph, S
RNA_parameter_list_create(&list, &ptr, func);
RNA_parameter_set_lookup(&list, "data", &bmain);
- RNA_parameter_set_lookup(&list, "depsgraph", &graph);
RNA_parameter_set_lookup(&list, "scene", &scene);
engine->type->ext.call(NULL, &ptr, func, &list);
RNA_parameter_list_free(&list);
}
-static void engine_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
+static void engine_render_to_image(RenderEngine *engine, Depsgraph *depsgraph)
{
extern FunctionRNA rna_RenderEngine_render_to_image_func;
PointerRNA ptr;
@@ -183,7 +183,7 @@ static void engine_render_to_image(RenderEngine *engine, struct Depsgraph *depsg
RNA_parameter_list_free(&list);
}
-static void engine_bake(RenderEngine *engine, struct Scene *scene,
+static void engine_bake(RenderEngine *engine, struct Depsgraph *depsgraph, struct Scene *scene,
struct Object *object, const int pass_type, const int pass_filter,
const int object_id, const struct BakePixel *pixel_array,
const int num_pixels, const int depth, void *result)
@@ -197,6 +197,7 @@ static void engine_bake(RenderEngine *engine, struct Scene *scene,
func = &rna_RenderEngine_bake_func;
RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "depsgraph", &depsgraph);
RNA_parameter_set_lookup(&list, "scene", &scene);
RNA_parameter_set_lookup(&list, "object", &object);
RNA_parameter_set_lookup(&list, "pass_type", &pass_type);
@@ -398,16 +399,6 @@ static PointerRNA rna_RenderEngine_render_get(PointerRNA *ptr)
}
}
-static PointerRNA rna_RenderEngine_view_layer_get(PointerRNA *ptr)
-{
- RenderEngine *engine = (RenderEngine *)ptr->data;
- if (engine->re != NULL) {
- ViewLayer *view_layer = RE_engine_get_view_layer(engine->re);
- return rna_pointer_inherit_refine(ptr, &RNA_ViewLayer, view_layer);
- }
- return rna_pointer_inherit_refine(ptr, &RNA_ViewLayer, NULL);
-}
-
static PointerRNA rna_RenderEngine_camera_override_get(PointerRNA *ptr)
{
RenderEngine *engine = (RenderEngine *)ptr->data;
@@ -512,17 +503,19 @@ static void rna_def_render_engine(BlenderRNA *brna)
RNA_def_function_ui_description(func, "Export scene data for render");
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
RNA_def_pointer(func, "data", "BlendData", "", "");
- RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "");
RNA_def_pointer(func, "scene", "Scene", "", "");
func = RNA_def_function(srna, "render_to_image", NULL);
RNA_def_function_ui_description(func, "Render scene into an image");
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
- RNA_def_pointer(func, "desgraph", "Depsgraph", "", "");
+ parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
func = RNA_def_function(srna, "bake", NULL);
RNA_def_function_ui_description(func, "Bake passes");
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_pointer(func, "scene", "Scene", "", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_pointer(func, "object", "Object", "", "");
@@ -769,11 +762,6 @@ static void rna_def_render_engine(BlenderRNA *brna)
prop = RNA_def_enum(func, "type", render_pass_type_items, SOCK_FLOAT, "Type", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- prop = RNA_def_property(srna, "view_layer", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "ViewLayer");
- RNA_def_property_pointer_funcs(prop, "rna_RenderEngine_view_layer_get", NULL, NULL, NULL);
- RNA_def_property_ui_text(prop, "Scene layer", "");
-
/* registration */
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c
index bc85e9c6503..d252c04742f 100644
--- a/source/blender/makesrna/intern/rna_rigidbody.c
+++ b/source/blender/makesrna/intern/rna_rigidbody.c
@@ -802,6 +802,7 @@ static void rna_def_rigidbody_world(BlenderRNA *brna)
prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_pointer_sdna(prop, NULL, "pointcache");
+ RNA_def_property_struct_type(prop, "PointCache");
RNA_def_property_ui_text(prop, "Point Cache", "");
/* effector weights */
@@ -1291,49 +1292,49 @@ static void rna_def_rigidbody_constraint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Z Angle Stiffness", "Stiffness on the Z rotational axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
- prop = RNA_def_property(srna, "spring_damping_x", PROP_FLOAT, PROP_FACTOR);
+ prop = RNA_def_property(srna, "spring_damping_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "spring_damping_x");
- RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_damping_x_set", NULL);
RNA_def_property_ui_text(prop, "Damping X", "Damping on the X axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
- prop = RNA_def_property(srna, "spring_damping_y", PROP_FLOAT, PROP_FACTOR);
+ prop = RNA_def_property(srna, "spring_damping_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "spring_damping_y");
- RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_damping_y_set", NULL);
RNA_def_property_ui_text(prop, "Damping Y", "Damping on the Y axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
- prop = RNA_def_property(srna, "spring_damping_z", PROP_FLOAT, PROP_FACTOR);
+ prop = RNA_def_property(srna, "spring_damping_z", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "spring_damping_z");
- RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_damping_z_set", NULL);
RNA_def_property_ui_text(prop, "Damping Z", "Damping on the Z axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
- prop = RNA_def_property(srna, "spring_damping_ang_x", PROP_FLOAT, PROP_FACTOR);
+ prop = RNA_def_property(srna, "spring_damping_ang_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "spring_damping_ang_x");
- RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_damping_ang_x_set", NULL);
RNA_def_property_ui_text(prop, "Damping X Angle", "Damping on the X rotational axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
- prop = RNA_def_property(srna, "spring_damping_ang_y", PROP_FLOAT, PROP_FACTOR);
+ prop = RNA_def_property(srna, "spring_damping_ang_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "spring_damping_ang_y");
- RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_damping_ang_y_set", NULL);
RNA_def_property_ui_text(prop, "Damping Y Angle", "Damping on the Y rotational axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
- prop = RNA_def_property(srna, "spring_damping_ang_z", PROP_FLOAT, PROP_FACTOR);
+ prop = RNA_def_property(srna, "spring_damping_ang_z", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "spring_damping_ang_z");
- RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_damping_ang_z_set", NULL);
RNA_def_property_ui_text(prop, "Damping Z Angle", "Damping on the Z rotational axis");
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 38149734bc2..a46c8e2f18f 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -638,7 +638,7 @@ static const EnumPropertyItem *rna_Property_tags_itemf(
int totitem = 0;
for (const EnumPropertyItem *struct_tags = RNA_struct_property_tag_defines(srna);
- struct_tags->identifier;
+ struct_tags != NULL && struct_tags->identifier != NULL;
struct_tags++)
{
memcpy(&tmp, struct_tags, sizeof(tmp));
@@ -1444,6 +1444,12 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b,
equals = false;
continue;
}
+ else if (iter_a.ptr.type == NULL) {
+ /* NULL RNA pointer... */
+ BLI_assert(iter_a.ptr.data == NULL);
+ BLI_assert(iter_b.ptr.data == NULL);
+ continue;
+ }
PropertyRNA *propname = RNA_struct_name_property(iter_a.ptr.type);
char propname_buff_a[256], propname_buff_b[256];
@@ -1452,6 +1458,10 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b,
if (propname != NULL) {
propname_a = RNA_property_string_get_alloc(&iter_a.ptr, propname, propname_buff_a, sizeof(propname_buff_a), NULL);
propname_b = RNA_property_string_get_alloc(&iter_b.ptr, propname, propname_buff_b, sizeof(propname_buff_b), NULL);
+ }
+ /* 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. */
+ if ((propname_a != NULL && propname_a[0] != '\0') || (propname_b != NULL && propname_b[0] != '\0')) {
if (!STREQ(propname_a, propname_b)) {
/* Same as above, not same structs. */
equals = false;
@@ -1466,7 +1476,7 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b,
}
}
- if (equals) {
+ if (equals || do_create) {
const bool no_ownership = (RNA_property_flag(prop_a) & PROP_PTR_NO_OWNERSHIP) != 0;
const int eq = rna_property_override_diff_propptr(
&iter_a.ptr, &iter_b.ptr, mode, no_ownership,
@@ -1475,10 +1485,10 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b,
}
if (propname_a != propname_buff_a) {
- MEM_freeN(propname_a);
+ MEM_SAFE_FREE(propname_a);
}
if (propname_b != propname_buff_b) {
- MEM_freeN(propname_b);
+ MEM_SAFE_FREE(propname_b);
}
MEM_SAFE_FREE(extended_rna_path);
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index e23fce47aad..3782e694d73 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -1469,11 +1469,11 @@ static void rna_Scene_use_nodes_update(bContext *C, PointerRNA *ptr)
static void rna_Physics_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->id.data;
- FOREACH_SCENE_OBJECT(scene, ob)
+ FOREACH_SCENE_OBJECT_BEGIN(scene, ob)
{
BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH);
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
}
static void rna_Scene_editmesh_select_mode_set(PointerRNA *ptr, const int *value)
@@ -1507,8 +1507,10 @@ static void rna_Scene_editmesh_select_mode_update(bContext *C, PointerRNA *UNUSE
me = NULL;
}
- WM_main_add_notifier(NC_GEOM | ND_SELECT, me);
- WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
+ if (me) {
+ DEG_id_tag_update(&me->id, DEG_TAG_SELECT_UPDATE);
+ WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
+ }
}
static void object_simplify_update(Object *ob)
@@ -1545,11 +1547,11 @@ static void rna_Scene_use_simplify_update(Main *UNUSED(bmain), Scene *UNUSED(sce
Scene *sce_iter;
Base *base;
- FOREACH_SCENE_OBJECT(sce, ob)
+ FOREACH_SCENE_OBJECT_BEGIN(sce, ob)
{
object_simplify_update(ob);
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
for (SETLOOPER_SET_ONLY(sce, sce_iter, base)) {
object_simplify_update(base->object);
@@ -1924,13 +1926,6 @@ char *rna_GPUDOF_path(PointerRNA *ptr)
return BLI_strdup("");
}
-static void rna_GPUFXSettings_fx_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- GPUFXSettings *fx_settings = ptr->data;
-
- BKE_screen_gpu_fx_validate(fx_settings);
-}
-
static void rna_GPUDOFSettings_blades_set(PointerRNA *ptr, const int value)
{
GPUDOFSettings *dofsettings = (GPUDOFSettings *)ptr->data;
@@ -4842,7 +4837,7 @@ static void rna_def_gpu_fx(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "fx_flag", GPU_FX_FLAG_DOF);
RNA_def_property_ui_text(prop, "Depth Of Field",
"Use depth of field on viewport using the values from active camera");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUFXSettings_fx_update");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "ssao", PROP_POINTER, PROP_NONE);
@@ -4853,7 +4848,7 @@ static void rna_def_gpu_fx(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_ssao", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "fx_flag", GPU_FX_FLAG_SSAO);
RNA_def_property_ui_text(prop, "SSAO", "Use screen space ambient occlusion of field on viewport");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUFXSettings_fx_update");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
}
static void rna_def_view_layers(BlenderRNA *brna, PropertyRNA *cprop)
@@ -5232,8 +5227,6 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
{FFMPEG_AVI, "AVI", 0, "AVI", ""},
{FFMPEG_MOV, "QUICKTIME", 0, "Quicktime", ""},
{FFMPEG_DV, "DV", 0, "DV", ""},
-// {FFMPEG_H264, "H264", 0, "H.264", ""}, not a container
-// {FFMPEG_XVID, "XVID", 0, "Xvid", ""}, not a container
{FFMPEG_OGG, "OGG", 0, "Ogg", ""},
{FFMPEG_MKV, "MKV", 0, "Matroska", ""},
{FFMPEG_FLV, "FLASH", 0, "Flash", ""},
@@ -5241,38 +5234,37 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
};
static const EnumPropertyItem ffmpeg_codec_items[] = {
- {AV_CODEC_ID_NONE, "NONE", 0, "None", ""},
- {AV_CODEC_ID_MPEG1VIDEO, "MPEG1", 0, "MPEG-1", ""},
- {AV_CODEC_ID_MPEG2VIDEO, "MPEG2", 0, "MPEG-2", ""},
- {AV_CODEC_ID_MPEG4, "MPEG4", 0, "MPEG-4(divx)", ""},
- {AV_CODEC_ID_HUFFYUV, "HUFFYUV", 0, "HuffYUV", ""},
+ {AV_CODEC_ID_NONE, "NONE", 0, "No Video", "Disables video output, for audio-only renders"},
+ {AV_CODEC_ID_DNXHD, "DNXHD", 0, "DNxHD", ""},
{AV_CODEC_ID_DVVIDEO, "DV", 0, "DV", ""},
- {AV_CODEC_ID_H264, "H264", 0, "H.264", ""},
- {AV_CODEC_ID_THEORA, "THEORA", 0, "Theora", ""},
- {AV_CODEC_ID_FLV1, "FLASH", 0, "Flash Video", ""},
{AV_CODEC_ID_FFV1, "FFV1", 0, "FFmpeg video codec #1", ""},
- {AV_CODEC_ID_QTRLE, "QTRLE", 0, "QT rle / QT Animation", ""},
- {AV_CODEC_ID_DNXHD, "DNXHD", 0, "DNxHD", ""},
+ {AV_CODEC_ID_FLV1, "FLASH", 0, "Flash Video", ""},
+ {AV_CODEC_ID_H264, "H264", 0, "H.264", ""},
+ {AV_CODEC_ID_HUFFYUV, "HUFFYUV", 0, "HuffYUV", ""},
+ {AV_CODEC_ID_MPEG1VIDEO, "MPEG1", 0, "MPEG-1", ""},
+ {AV_CODEC_ID_MPEG2VIDEO, "MPEG2", 0, "MPEG-2", ""},
+ {AV_CODEC_ID_MPEG4, "MPEG4", 0, "MPEG-4 (divx)", ""},
{AV_CODEC_ID_PNG, "PNG", 0, "PNG", ""},
+ {AV_CODEC_ID_QTRLE, "QTRLE", 0, "QT rle / QT Animation", ""},
+ {AV_CODEC_ID_THEORA, "THEORA", 0, "Theora", ""},
+ {AV_CODEC_ID_VP9, "WEBM", 0, "WEBM / VP9", ""},
{0, NULL, 0, NULL, NULL}
};
+ /* Recommendations come from the FFmpeg wiki, https://trac.ffmpeg.org/wiki/Encode/VP9.
+ * The label for BEST has been changed to "Slowest" so that it fits the "Encoding Speed"
+ * property label in the UI. */
static const EnumPropertyItem ffmpeg_preset_items[] = {
- {FFM_PRESET_ULTRAFAST, "ULTRAFAST", 0, "Ultra fast; biggest file", ""},
- {FFM_PRESET_SUPERFAST, "SUPERFAST", 0, "Super fast", ""},
- {FFM_PRESET_VERYFAST, "VERYFAST", 0, "Very fast", ""},
- {FFM_PRESET_FASTER, "FASTER", 0, "Faster", ""},
- {FFM_PRESET_FAST, "FAST", 0, "Fast", ""},
- {FFM_PRESET_MEDIUM, "MEDIUM", 0, "Medium speed", ""},
- {FFM_PRESET_SLOW, "SLOW", 0, "Slow", ""},
- {FFM_PRESET_SLOWER, "SLOWER", 0, "Slower", ""},
- {FFM_PRESET_VERYSLOW, "VERYSLOW", 0, "Very slow; smallest file", ""},
+ {FFM_PRESET_BEST, "BEST", 0, "Slowest",
+ "Recommended if you have lots of time and want the best compression efficiency"},
+ {FFM_PRESET_GOOD, "GOOD", 0, "Good", "The default and recommended for most applications"},
+ {FFM_PRESET_REALTIME, "REALTIME", 0, "Realtime", "Recommended for fast encoding"},
{0, NULL, 0, NULL, NULL}
};
static const EnumPropertyItem ffmpeg_crf_items[] = {
- {FFM_CRF_NONE, "NONE", 0, "None; use custom bitrate",
- "Use constant bit rate, rather than constant output quality"},
+ {FFM_CRF_NONE, "NONE", 0, "Constant Bitrate",
+ "Configure constant bit rate, rather than constant output quality"},
{FFM_CRF_LOSSLESS, "LOSSLESS", 0, "Lossless", ""},
{FFM_CRF_PERC_LOSSLESS, "PERC_LOSSLESS", 0, "Perceptually lossless", ""},
{FFM_CRF_HIGH, "HIGH", 0, "High quality", ""},
@@ -5284,14 +5276,14 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
};
static const EnumPropertyItem ffmpeg_audio_codec_items[] = {
- {AV_CODEC_ID_NONE, "NONE", 0, "None", ""},
- {AV_CODEC_ID_MP2, "MP2", 0, "MP2", ""},
- {AV_CODEC_ID_MP3, "MP3", 0, "MP3", ""},
- {AV_CODEC_ID_AC3, "AC3", 0, "AC3", ""},
+ {AV_CODEC_ID_NONE, "NONE", 0, "No Audio", "Disables audio output, for video-only renders"},
{AV_CODEC_ID_AAC, "AAC", 0, "AAC", ""},
- {AV_CODEC_ID_VORBIS, "VORBIS", 0, "Vorbis", ""},
+ {AV_CODEC_ID_AC3, "AC3", 0, "AC3", ""},
{AV_CODEC_ID_FLAC, "FLAC", 0, "FLAC", ""},
+ {AV_CODEC_ID_MP2, "MP2", 0, "MP2", ""},
+ {AV_CODEC_ID_MP3, "MP3", 0, "MP3", ""},
{AV_CODEC_ID_PCM_S16LE, "PCM", 0, "PCM", ""},
+ {AV_CODEC_ID_VORBIS, "VORBIS", 0, "Vorbis", ""},
{0, NULL, 0, NULL, NULL}
};
#endif
@@ -5323,7 +5315,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_enum_items(prop, ffmpeg_codec_items);
RNA_def_property_enum_default(prop, AV_CODEC_ID_H264);
- RNA_def_property_ui_text(prop, "Codec", "FFmpeg codec to use");
+ RNA_def_property_ui_text(prop, "Video Codec", "FFmpeg codec to use for video output");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_FFmpegSettings_codec_settings_update");
prop = RNA_def_property(srna, "video_bitrate", PROP_INT, PROP_NONE);
@@ -5402,7 +5394,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
RNA_def_property_enum_bitflag_sdna(prop, NULL, "ffmpeg_preset");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_enum_items(prop, ffmpeg_preset_items);
- RNA_def_property_enum_default(prop, FFM_PRESET_MEDIUM);
+ RNA_def_property_enum_default(prop, FFM_PRESET_GOOD);
RNA_def_property_ui_text(prop, "Encoding speed",
"Tradeoff between encoding speed and compression ratio");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
@@ -5724,7 +5716,8 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "filter_size", PROP_FLOAT, PROP_PIXEL);
RNA_def_property_float_sdna(prop, NULL, "gauss");
- RNA_def_property_range(prop, 0.5f, 1.5f);
+ RNA_def_property_range(prop, 0.0f, 500.0f);
+ RNA_def_property_ui_range(prop, 0.01f, 10.0f, 1, 2);
RNA_def_property_ui_text(prop, "Filter Size", "Width over which the reconstruction filter combines samples");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
@@ -6146,7 +6139,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_stamp_date", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_DATE);
- RNA_def_property_ui_text(prop, "Stamp Date", "Include the current date in image metadata");
+ RNA_def_property_ui_text(prop, "Stamp Date", "Include the current date in image/video metadata");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "use_stamp_frame", PROP_BOOLEAN, PROP_NONE);
@@ -6154,6 +6147,11 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Stamp Frame", "Include the frame number in image metadata");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ prop = RNA_def_property(srna, "use_stamp_frame_range", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_FRAME_RANGE);
+ RNA_def_property_ui_text(prop, "Stamp Frame", "Include the rendered frame range in image/video metadata");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
prop = RNA_def_property(srna, "use_stamp_camera", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_CAMERA);
RNA_def_property_ui_text(prop, "Stamp Camera", "Include the name of the active camera in image metadata");
@@ -6166,12 +6164,12 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_stamp_scene", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_SCENE);
- RNA_def_property_ui_text(prop, "Stamp Scene", "Include the name of the active scene in image metadata");
+ RNA_def_property_ui_text(prop, "Stamp Scene", "Include the name of the active scene in image/video metadata");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "use_stamp_note", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_NOTE);
- RNA_def_property_ui_text(prop, "Stamp Note", "Include a custom note in image metadata");
+ RNA_def_property_ui_text(prop, "Stamp Note", "Include a custom note in image/video metadata");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "use_stamp_marker", PROP_BOOLEAN, PROP_NONE);
@@ -6181,7 +6179,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_stamp_filename", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_FILENAME);
- RNA_def_property_ui_text(prop, "Stamp Filename", "Include the .blend filename in image metadata");
+ RNA_def_property_ui_text(prop, "Stamp Filename", "Include the .blend filename in image/video metadata");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "use_stamp_sequencer_strip", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index 7d8bf4949d5..d2afb43d65e 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -90,11 +90,7 @@ static void rna_Scene_frame_set(Scene *scene, Main *bmain, int frame, float subf
view_layer = view_layer->next)
{
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
- BKE_scene_graph_update_for_newframe(bmain->eval_ctx,
- depsgraph,
- bmain,
- scene,
- view_layer);
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
}
#ifdef WITH_PYTHON
@@ -140,11 +136,7 @@ static void rna_Scene_update_tagged(Scene *scene, Main *bmain)
view_layer = view_layer->next)
{
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
- BKE_scene_graph_update_tagged(bmain->eval_ctx,
- depsgraph,
- bmain,
- scene,
- view_layer);
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
}
#ifdef WITH_PYTHON
@@ -171,24 +163,15 @@ static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, int previe
}
static void rna_Scene_ray_cast(
- Scene *scene, ViewLayer *view_layer, const char *engine_id,
+ Scene *scene, ViewLayer *view_layer,
float origin[3], float direction[3], float ray_dist,
int *r_success, float r_location[3], float r_normal[3], int *r_index,
Object **r_ob, float r_obmat[16])
{
- RenderEngineType *engine_type;
-
- if (engine_id == NULL || engine_id[0] == '\0') {
- engine_type = RE_engines_find(scene->view_render.engine_id);
- }
- else {
- engine_type = RE_engines_find(engine_id);
- }
-
normalize_v3(direction);
SnapObjectContext *sctx = ED_transform_snap_object_context_create(
- G.main, scene, view_layer, engine_type, 0);
+ G.main, scene, view_layer, 0);
bool ret = ED_transform_snap_object_project_ray_ex(
sctx,
@@ -290,70 +273,6 @@ static void rna_Scene_alembic_export(
#endif
-#ifdef WITH_COLLADA
-/* don't remove this, as COLLADA exporting cannot be done through operators in render() callback. */
-#include "../../collada/collada.h"
-
-/* Note: This definition must match to the generated function call */
-static void rna_Scene_collada_export(
- Scene *scene,
- bContext *C,
- const char *filepath,
- int apply_modifiers,
-
- int export_mesh_type,
- int selected,
- int include_children,
- int include_armatures,
- int include_shapekeys,
- int deform_bones_only,
- int active_uv_only,
- int include_material_textures,
- int use_texture_copies,
- int triangulate,
- int use_object_instantiation,
- int use_blender_profile,
- int sort_by_name,
- int export_transformation_type,
- int open_sim,
- int limit_precision,
- int keep_bind_info)
-{
- EvaluationContext eval_ctx;
-
- CTX_data_eval_ctx(C, &eval_ctx);
-
- collada_export(&eval_ctx,
- scene,
- CTX_data_view_layer(C),
- filepath,
-
- apply_modifiers,
- export_mesh_type,
-
- selected,
- include_children,
- include_armatures,
- include_shapekeys,
- deform_bones_only,
-
- active_uv_only,
- include_material_textures,
- use_texture_copies,
-
- triangulate,
- use_object_instantiation,
- use_blender_profile,
- sort_by_name,
-
- export_transformation_type,
- open_sim,
- limit_precision,
- keep_bind_info);
-}
-
-#endif
-
#else
void RNA_api_scene(StructRNA *srna)
@@ -386,7 +305,6 @@ void RNA_api_scene(StructRNA *srna)
RNA_def_function_ui_description(func, "Cast a ray onto in object space");
parm = RNA_def_pointer(func, "view_layer", "ViewLayer", "", "Scene Layer");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
- parm = RNA_def_string(func, "engine", NULL, MAX_NAME, "Engine", "Render engine, use scene one by default");
/* ray start and end */
parm = RNA_def_float_vector(func, "origin", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
@@ -412,67 +330,6 @@ void RNA_api_scene(StructRNA *srna)
parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
RNA_def_function_output(func, parm);
-#ifdef WITH_COLLADA
- /* don't remove this, as COLLADA exporting cannot be done through operators in render() callback. */
- func = RNA_def_function(srna, "collada_export", "rna_Scene_collada_export");
- parm = RNA_def_string(func, "filepath", NULL, FILE_MAX, "File Path", "File path to write Collada file");
- RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- RNA_def_property_subtype(parm, PROP_FILEPATH); /* allow non utf8 */
-
- RNA_def_boolean(func, "apply_modifiers", false,
- "Apply Modifiers", "Apply modifiers to exported mesh (non destructive))");
-
- RNA_def_int(func, "export_mesh_type", 0, INT_MIN, INT_MAX,
- "Resolution", "Modifier resolution for export", INT_MIN, INT_MAX);
-
- RNA_def_boolean(func, "selected", false, "Selection Only", "Export only selected elements");
-
- RNA_def_boolean(func, "include_children", false,
- "Include Children", "Export all children of selected objects (even if not selected)");
-
- RNA_def_boolean(func, "include_armatures", false,
- "Include Armatures", "Export related armatures (even if not selected)");
-
- RNA_def_boolean(func, "include_shapekeys", true, "Include Shape Keys", "Export all Shape Keys from Mesh Objects");
-
- RNA_def_boolean(func, "deform_bones_only", false,
- "Deform Bones only", "Only export deforming bones with armatures");
-
- RNA_def_boolean(func, "active_uv_only", false, "Only Selected UV Map", "Export only the selected UV Map");
-
- RNA_def_boolean(func, "include_material_textures", false,
- "Include Material Textures", "Export textures assigned to the object Materials");
-
- RNA_def_boolean(func, "use_texture_copies", true,
- "Copy", "Copy textures to same folder where the .dae file is exported");
-
- RNA_def_boolean(func, "triangulate", true, "Triangulate", "Export Polygons (Quads & NGons) as Triangles");
-
- RNA_def_boolean(func, "use_object_instantiation", true,
- "Use Object Instances", "Instantiate multiple Objects from same Data");
-
- RNA_def_boolean(func, "use_blender_profile", true, "Use Blender Profile",
- "Export additional Blender specific information (for material, shaders, bones, etc.)");
-
- RNA_def_boolean(func, "sort_by_name", false, "Sort by Object name", "Sort exported data by Object name");
-
- RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX,
- "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
-
- RNA_def_boolean(func, "open_sim", false,
- "Export to SL/OpenSim", "Compatibility mode for SL, OpenSim and other compatible online worlds");
-
- RNA_def_boolean(func, "limit_precision", false,
- "Limit Precision",
- "Reduce the precision of the exported data to 6 digits");
-
- RNA_def_boolean(func, "keep_bind_info", false,
- "Keep Bind Info",
- "Store bind pose information in custom bone properties for later use during Collada export");
-
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
-
-#endif
#ifdef WITH_ALEMBIC
/* XXX Deprecated, will be removed in 2.8 in favour of calling the export operator. */
@@ -491,7 +348,7 @@ void RNA_api_scene(StructRNA *srna)
RNA_def_float(func, "shutter_close", 1.0f, -1.0f, 1.0f, "Shutter close", "", -1.0f, 1.0f);
RNA_def_boolean(func, "selected_only" , 0, "Selected only", "Export only selected objects");
RNA_def_boolean(func, "uvs" , 1, "UVs", "Export UVs");
- RNA_def_boolean(func, "normals" , 1, "Normals", "Export cormals");
+ RNA_def_boolean(func, "normals" , 1, "Normals", "Export normals");
RNA_def_boolean(func, "vcolors" , 0, "Vertex colors", "Export vertex colors");
RNA_def_boolean(func, "apply_subdiv" , 1, "Subsurfs as meshes", "Export subdivision surfaces as meshes");
RNA_def_boolean(func, "flatten" , 0, "Flatten hierarchy", "Flatten hierarchy");
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index 0221a40cb5d..97b89937081 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -333,11 +333,6 @@ static void rna_def_region(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Region", "Region in a subdivided screen area");
RNA_def_struct_sdna(srna, "ARegion");
- prop = RNA_def_property(srna, "id", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "swinid");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Region ID", "Unique ID for this region");
-
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "regiontype");
RNA_def_property_enum_items(prop, rna_enum_region_type_items);
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index 3977f73cd3d..13833c86d9a 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -107,6 +107,7 @@ const EnumPropertyItem rna_enum_symmetrize_direction_items[] = {
#include "BKE_pointcache.h"
#include "BKE_particle.h"
#include "BKE_pbvh.h"
+#include "BKE_object.h"
#include "DEG_depsgraph.h"
@@ -158,7 +159,7 @@ static void rna_ParticleEdit_redo(bContext *C, PointerRNA *UNUSED(ptr))
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = OBACT(view_layer);
- PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
if (!edit)
return;
@@ -179,8 +180,8 @@ static void rna_ParticleEdit_tool_set(PointerRNA *ptr, int value)
ParticleEditSettings *pset = (ParticleEditSettings *)ptr->data;
/* redraw hair completely if weight brush is/was used */
- if ((pset->brushtype == PE_BRUSH_WEIGHT || value == PE_BRUSH_WEIGHT) && pset->view_layer) {
- Object *ob = (pset->view_layer->basact) ? pset->view_layer->basact->object : NULL;
+ if ((pset->brushtype == PE_BRUSH_WEIGHT || value == PE_BRUSH_WEIGHT) && pset->object) {
+ Object *ob = pset->object;
if (ob) {
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
@@ -221,14 +222,14 @@ static int rna_ParticleEdit_editable_get(PointerRNA *ptr)
{
ParticleEditSettings *pset = (ParticleEditSettings *)ptr->data;
- return (pset->object && pset->scene && PE_get_current(pset->scene, pset->view_layer, pset->object));
+ return (pset->object && pset->scene && PE_get_current(pset->scene, pset->object));
}
static int rna_ParticleEdit_hair_get(PointerRNA *ptr)
{
ParticleEditSettings *pset = (ParticleEditSettings *)ptr->data;
if (pset->scene) {
- PTCacheEdit *edit = PE_get_current(pset->scene, pset->view_layer, pset->object);
+ PTCacheEdit *edit = PE_get_current(pset->scene, pset->object);
return (edit && edit->psys);
}
@@ -412,6 +413,7 @@ static void rna_ImaPaint_canvas_update(bContext *C, PointerRNA *UNUSED(ptr))
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = OBACT(view_layer);
+ Object *obedit = OBEDIT_FROM_OBACT(ob);
bScreen *sc;
Image *ima = scene->toolsettings->imapaint.canvas;
@@ -424,7 +426,7 @@ static void rna_ImaPaint_canvas_update(bContext *C, PointerRNA *UNUSED(ptr))
SpaceImage *sima = (SpaceImage *)slink;
if (!sima->pin)
- ED_space_image_set(sima, scene, scene->obedit, ima);
+ ED_space_image_set(sima, scene, obedit, ima);
}
}
}
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 61ac81a6d1c..33621af69af 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -38,10 +38,11 @@
#include "BLT_translation.h"
#include "BKE_animsys.h"
-#include "BKE_global.h"
#include "BKE_sequencer.h"
#include "BKE_sound.h"
+#include "IMB_metadata.h"
+
#include "MEM_guardedalloc.h"
#include "RNA_access.h"
@@ -75,6 +76,7 @@ const EnumPropertyItem rna_enum_sequence_modifier_type_items[] = {
#include "BKE_report.h"
#include "BKE_idprop.h"
+#include "BKE_movieclip.h"
#include "WM_api.h"
@@ -587,6 +589,27 @@ static IDProperty *rna_Sequence_idprops(PointerRNA *ptr, bool create)
return seq->prop;
}
+static PointerRNA rna_MovieSequence_metadata_get(Sequence *seq)
+{
+ if (seq == NULL || seq->anims.first == NULL) {
+ return PointerRNA_NULL;
+ }
+
+ StripAnim *sanim = seq->anims.first;
+ if (sanim->anim == NULL) {
+ return PointerRNA_NULL;
+ }
+
+ IDProperty *metadata = IMB_anim_load_metadata(sanim->anim);
+ if (metadata == NULL) {
+ return PointerRNA_NULL;
+ }
+
+ PointerRNA ptr;
+ RNA_pointer_create(NULL, &RNA_IDPropertyWrapPtr, metadata, &ptr);
+ return ptr;
+}
+
static PointerRNA rna_SequenceEditor_meta_stack_get(CollectionPropertyIterator *iter)
{
ListBaseIterator *internal = &iter->internal.listbase;
@@ -1085,6 +1108,13 @@ static void rna_Sequence_modifier_clear(Sequence *seq, bContext *C)
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL);
}
+static float rna_Sequence_fps_get(PointerRNA *ptr)
+{
+ Scene *scene = (Scene *)ptr->id.data;
+ Sequence *seq = (Sequence *)(ptr->data);
+ return BKE_sequence_get_fps(scene, seq);
+}
+
#else
static void rna_def_strip_element(BlenderRNA *brna)
@@ -1840,6 +1870,16 @@ static void rna_def_color_management(StructRNA *srna)
RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings");
}
+static void rna_def_movie_types(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "fps", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "FPS", "Frames per second");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_float_funcs(prop, "rna_Sequence_fps_get", NULL, NULL);
+}
+
static void rna_def_image(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1939,13 +1979,16 @@ static void rna_def_scene(BlenderRNA *brna)
rna_def_filter_video(srna);
rna_def_proxy(srna);
rna_def_input(srna);
+ rna_def_movie_types(srna);
}
static void rna_def_movie(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
srna = RNA_def_struct(brna, "MovieSequence", "Sequence");
RNA_def_struct_ui_text(srna, "Movie Sequence", "Sequence strip to load a video");
RNA_def_struct_sdna(srna, "Sequence");
@@ -1977,6 +2020,14 @@ static void rna_def_movie(BlenderRNA *brna)
"rna_Sequence_filepath_set");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_filepath_update");
+ /* metadata */
+ func = RNA_def_function(srna, "metadata", "rna_MovieSequence_metadata_get");
+ RNA_def_function_ui_description(func, "Retrieve metadata of the movie file");
+ /* return type */
+ parm = RNA_def_pointer(func, "metadata", "IDPropertyWrapPtr", "", "Dict-like object containing the metadata");
+ RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
+ RNA_def_function_return(func, parm);
+
/* multiview */
prop = RNA_def_property(srna, "use_multiview", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_VIEWS);
@@ -1999,6 +2050,7 @@ static void rna_def_movie(BlenderRNA *brna)
rna_def_proxy(srna);
rna_def_input(srna);
rna_def_color_management(srna);
+ rna_def_movie_types(srna);
}
static void rna_def_movieclip(BlenderRNA *brna)
@@ -2024,6 +2076,7 @@ static void rna_def_movieclip(BlenderRNA *brna)
rna_def_filter_video(srna);
rna_def_input(srna);
+ rna_def_movie_types(srna);
}
static void rna_def_mask(BlenderRNA *brna)
@@ -2160,6 +2213,7 @@ static void rna_def_wipe(StructRNA *srna)
prop = RNA_def_property(srna, "transition_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "wipetype");
RNA_def_property_enum_items(prop, wipe_type_items);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SEQUENCE);
RNA_def_property_ui_text(prop, "Transition Type", "");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
}
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
index ac13f9d8294..d5580ae35ad 100644
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -42,7 +42,7 @@
#include "BKE_pointcache.h"
#include "DNA_modifier_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_smoke_types.h"
@@ -364,6 +364,42 @@ static void rna_SmokeModifier_heat_grid_get(PointerRNA *ptr, float *values)
#endif
}
+static void rna_SmokeModifier_temperature_grid_get(PointerRNA *ptr, float *values)
+{
+#ifdef WITH_SMOKE
+ SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
+ int length[RNA_MAX_ARRAY_DIMENSION];
+ int size = rna_SmokeModifier_grid_get_length(ptr, length);
+ float *flame;
+
+ BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);
+
+ if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt) {
+ flame = smoke_turbulence_get_flame(sds->wt);
+ }
+ else {
+ flame = smoke_get_flame(sds->fluid);
+ }
+
+ if (flame) {
+ /* Output is such that 0..1 maps to 0..1000K */
+ float offset = sds->flame_ignition;
+ float scale = sds->flame_max_temp - sds->flame_ignition;
+
+ for (int i = 0; i < size; i++) {
+ values[i] = (flame[i] > 0.01f) ? offset + flame[i] * scale : 0.0f;
+ }
+ }
+ else {
+ memset(values, 0, size * sizeof(float));
+ }
+
+ BLI_rw_mutex_unlock(sds->fluid_mutex);
+#else
+ UNUSED_VARS(ptr, values);
+#endif
+}
+
static void rna_SmokeFlow_density_vgroup_get(PointerRNA *ptr, char *value)
{
SmokeFlowSettings *flow = (SmokeFlowSettings *)ptr->data;
@@ -588,6 +624,7 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_pointer_sdna(prop, NULL, "point_cache[0]");
+ RNA_def_property_struct_type(prop, "PointCache");
RNA_def_property_ui_text(prop, "Point Cache", "");
prop = RNA_def_property(srna, "point_cache_compress_type", PROP_ENUM, PROP_NONE);
@@ -679,6 +716,14 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
RNA_def_property_float_funcs(prop, "rna_SmokeModifier_heat_grid_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Heat Grid", "Smoke heat grid");
+ prop = RNA_def_property(srna, "temperature_grid", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_array(prop, 32);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_dynamic_array_funcs(prop, "rna_SmokeModifier_grid_get_length");
+ RNA_def_property_float_funcs(prop, "rna_SmokeModifier_temperature_grid_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Temperature Grid", "Smoke temperature grid, range 0..1 represents 0..1000K");
+
prop = RNA_def_property(srna, "cell_size", PROP_FLOAT, PROP_XYZ); /* can change each frame when using adaptive domain */
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "cell_size", "Cell Size");
@@ -856,6 +901,14 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "ColorRamp");
RNA_def_property_ui_text(prop, "Color Ramp", "");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ prop = RNA_def_property(srna, "clipping", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "clipping");
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 3);
+ RNA_def_property_ui_text(prop, "Clipping",
+ "Value under which voxels are considered empty space to optimize caching or rendering");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
}
static void rna_def_smoke_flow_settings(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 4ff8444cd71..2d8385a5f83 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -64,28 +64,38 @@
const EnumPropertyItem rna_enum_space_type_items[] = {
/* empty must be here for python, is skipped for UI */
{SPACE_EMPTY, "EMPTY", ICON_NONE, "Empty", ""},
+
+ /* General */
+ {0, "", ICON_NONE, "General", ""},
{SPACE_VIEW3D, "VIEW_3D", ICON_VIEW3D, "3D View", "3D viewport"},
- {0, "", ICON_NONE, NULL, NULL},
+ {SPACE_IMAGE, "IMAGE_EDITOR", ICON_IMAGE_COL, "UV/Image Editor", "View and edit images and UV Maps"},
+ {SPACE_NODE, "NODE_EDITOR", ICON_NODETREE, "Node Editor", "Editor for node-based shading and compositing tools"},
+ {SPACE_SEQ, "SEQUENCE_EDITOR", ICON_SEQUENCE, "Video Sequencer", "Video editing tools"},
+ {SPACE_CLIP, "CLIP_EDITOR", ICON_CLIP, "Movie Clip Editor", "Motion tracking tools"},
+
+ /* Animation */
+ {0, "", ICON_NONE, "Animation", ""},
{SPACE_TIME, "TIMELINE", ICON_TIME, "Timeline", "Timeline and playback controls"},
{SPACE_IPO, "GRAPH_EDITOR", ICON_IPO, "Graph Editor", "Edit drivers and keyframe interpolation"},
{SPACE_ACTION, "DOPESHEET_EDITOR", ICON_ACTION, "Dope Sheet", "Adjust timing of keyframes"},
{SPACE_NLA, "NLA_EDITOR", ICON_NLA, "NLA Editor", "Combine and layer Actions"},
- {0, "", ICON_NONE, NULL, NULL},
- {SPACE_IMAGE, "IMAGE_EDITOR", ICON_IMAGE_COL, "UV/Image Editor", "View and edit images and UV Maps"},
- {SPACE_CLIP, "CLIP_EDITOR", ICON_CLIP, "Movie Clip Editor", "Motion tracking tools"},
- {SPACE_SEQ, "SEQUENCE_EDITOR", ICON_SEQUENCE, "Video Sequence Editor", "Video editing tools"},
- {SPACE_NODE, "NODE_EDITOR", ICON_NODETREE, "Node Editor", "Editor for node-based shading and compositing tools"},
+
+ /* Scripting */
+ {0, "", ICON_NONE, "Scripting", ""},
{SPACE_TEXT, "TEXT_EDITOR", ICON_TEXT, "Text Editor", "Edit scripts and in-file documentation"},
{SPACE_LOGIC, "LOGIC_EDITOR", ICON_LOGIC, "Logic Editor", "Game logic editing"},
- {0, "", ICON_NONE, NULL, NULL},
- {SPACE_BUTS, "PROPERTIES", ICON_BUTS, "Properties", "Edit properties of active object and related data-blocks"},
+ {SPACE_CONSOLE, "CONSOLE", ICON_CONSOLE, "Python Console", "Interactive programmatic console for "
+ "advanced editing and script development"},
+ {SPACE_INFO, "INFO", ICON_INFO, "Info", "Main menu bar and list of error messages "
+ "(drag down to expand and display)"},
+
+ /* Data */
+ {0, "", ICON_NONE, "Data", ""},
{SPACE_OUTLINER, "OUTLINER", ICON_OOPS, "Outliner", "Overview of scene graph and all available data-blocks"},
- {SPACE_USERPREF, "USER_PREFERENCES", ICON_PREFERENCES, "User Preferences", "Edit persistent configuration settings"},
- {SPACE_INFO, "INFO", ICON_INFO, "Info", "Main menu bar and list of error messages (drag down to expand and display)"},
- {0, "", ICON_NONE, NULL, NULL},
+ {SPACE_BUTS, "PROPERTIES", ICON_BUTS, "Properties", "Edit properties of active object and related data-blocks"},
{SPACE_FILE, "FILE_BROWSER", ICON_FILESEL, "File Browser", "Browse for files and assets"},
- {0, "", ICON_NONE, NULL, NULL},
- {SPACE_CONSOLE, "CONSOLE", ICON_CONSOLE, "Python Console", "Interactive programmatic console for advanced editing and script development"},
+ {SPACE_USERPREF, "USER_PREFERENCES", ICON_PREFERENCES, "User Preferences",
+ "Edit persistent configuration settings"},
{0, NULL, 0, NULL, NULL}
};
@@ -573,12 +583,12 @@ static void rna_SpaceView3D_layer_update(Main *bmain, Scene *UNUSED(scene), Poin
DEG_on_visible_update(bmain, false);
}
-static void rna_SpaceView3D_viewport_shade_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_SpaceView3D_viewport_shade_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
View3D *v3d = (View3D *)(ptr->data);
ScrArea *sa = rna_area_from_space(ptr);
- ED_view3d_shade_update(bmain, scene, v3d, sa);
+ ED_view3d_shade_update(bmain, v3d, sa);
}
static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -857,28 +867,30 @@ static int rna_SpaceImageEditor_show_uvedit_get(PointerRNA *ptr)
{
SpaceImage *sima = (SpaceImage *)(ptr->data);
bScreen *sc = (bScreen *)ptr->id.data;
- Scene *scene = ED_screen_scene_find(sc, G.main->wm.first);
-
- return ED_space_image_show_uvedit(sima, scene->obedit);
+ 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);
+ return ED_space_image_show_uvedit(sima, obedit);
}
static int rna_SpaceImageEditor_show_maskedit_get(PointerRNA *ptr)
{
SpaceImage *sima = (SpaceImage *)(ptr->data);
bScreen *sc = (bScreen *)ptr->id.data;
- Scene *scene = ED_screen_scene_find(sc, G.main->wm.first);
- ViewLayer *view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene);
-
- return ED_space_image_check_show_maskedit(view_layer, sima);
+ 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);
}
static void rna_SpaceImageEditor_image_set(PointerRNA *ptr, PointerRNA value)
{
SpaceImage *sima = (SpaceImage *)(ptr->data);
bScreen *sc = (bScreen *)ptr->id.data;
- Scene *scene = ED_screen_scene_find(sc, G.main->wm.first);
-
- ED_space_image_set(sima, scene, scene->obedit, (Image *)value.data);
+ wmWindow *win;
+ Scene *scene = ED_screen_scene_find_with_window(sc, G.main->wm.first, &win);
+ ViewLayer *view_layer = WM_window_get_active_view_layer(win);
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
+ ED_space_image_set(sima, scene, obedit, (Image *)value.data);
}
static void rna_SpaceImageEditor_mask_set(PointerRNA *ptr, PointerRNA value)
diff --git a/source/blender/makesrna/intern/rna_text_api.c b/source/blender/makesrna/intern/rna_text_api.c
index 0287f74587b..d7a862fecbc 100644
--- a/source/blender/makesrna/intern/rna_text_api.c
+++ b/source/blender/makesrna/intern/rna_text_api.c
@@ -40,13 +40,13 @@
static void rna_Text_clear(Text *text)
{
- BKE_text_clear(text);
+ BKE_text_clear(text, NULL);
WM_main_add_notifier(NC_TEXT | NA_EDITED, text);
}
static void rna_Text_write(Text *text, const char *str)
{
- BKE_text_write(text, str);
+ BKE_text_write(text, NULL, str);
WM_main_add_notifier(NC_TEXT | NA_EDITED, text);
}
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index f2527a8a5e9..40657b3a225 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -267,6 +267,13 @@ static StructRNA *rna_Panel_register(
else
BLI_addtail(&art->paneltypes, pt);
+ {
+ const char *owner_id = RNA_struct_state_owner_get();
+ if (owner_id) {
+ BLI_strncpy(pt->owner_id, owner_id, sizeof(pt->owner_id));
+ }
+ }
+
/* update while blender is running */
WM_main_add_notifier(NC_WINDOW, NULL);
@@ -773,6 +780,13 @@ static StructRNA *rna_Menu_register(
mt->poll = (have_function[0]) ? menu_poll : NULL;
mt->draw = (have_function[1]) ? menu_draw : NULL;
+ {
+ const char *owner_id = RNA_struct_state_owner_get();
+ if (owner_id) {
+ BLI_strncpy(mt->owner_id, owner_id, sizeof(mt->owner_id));
+ }
+ }
+
WM_menutype_add(mt);
/* update while blender is running */
@@ -1023,6 +1037,10 @@ static void rna_def_panel(BlenderRNA *brna)
RNA_def_property_string_sdna(prop, NULL, "type->category");
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+ prop = RNA_def_property(srna, "bl_owner_id", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "type->owner_id");
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type->space_type");
RNA_def_property_enum_items(prop, rna_enum_space_type_items);
@@ -1290,6 +1308,10 @@ static void rna_def_menu(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
+ prop = RNA_def_property(srna, "bl_owner_id", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "type->owner_id");
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
RNA_define_verify_sdna(1);
}
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 4f396ea6161..88330ad2a8f 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -395,26 +395,23 @@ static void rna_userdef_autosave_update(Main *bmain, Scene *scene, PointerRNA *p
static bAddon *rna_userdef_addon_new(void)
{
- bAddon *bext = MEM_callocN(sizeof(bAddon), "bAddon");
- BLI_addtail(&U.addons, bext);
- return bext;
+ ListBase *addons_list = &U.addons;
+ bAddon *addon = BKE_addon_new();
+ BLI_addtail(addons_list, addon);
+ return addon;
}
-static void rna_userdef_addon_remove(ReportList *reports, PointerRNA *path_cmp_ptr)
+static void rna_userdef_addon_remove(ReportList *reports, PointerRNA *addon_ptr)
{
- bAddon *bext = path_cmp_ptr->data;
- if (BLI_findindex(&U.addons, bext) == -1) {
+ ListBase *addons_list = &U.addons;
+ bAddon *addon = addon_ptr->data;
+ if (BLI_findindex(addons_list, addon) == -1) {
BKE_report(reports, RPT_ERROR, "Add-on is no longer valid");
return;
}
-
- if (bext->prop) {
- IDP_FreeProperty(bext->prop);
- MEM_freeN(bext->prop);
- }
-
- BLI_freelinkN(&U.addons, bext);
- RNA_POINTER_INVALIDATE(path_cmp_ptr);
+ BLI_remlink(addons_list, addon);
+ BKE_addon_free(addon);
+ RNA_POINTER_INVALIDATE(addon_ptr);
}
static bPathCompare *rna_userdef_pathcompare_new(void)
@@ -447,6 +444,12 @@ static void rna_userdef_text_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P
WM_main_add_notifier(NC_WINDOW, NULL);
}
+static void rna_userdef_text_antialiasing_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ BLF_antialias_set((U.text_render & USER_TEXT_DISABLE_AA) == 0);
+ rna_userdef_text_update(bmain, scene, ptr);
+}
+
static PointerRNA rna_Theme_space_generic_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_ThemeSpaceGeneric, ptr->data);
@@ -3493,12 +3496,12 @@ static void rna_def_userdef_view(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Global Pivot", "Lock the same rotation/scaling pivot in all 3D Views");
prop = RNA_def_property(srna, "use_mouse_depth_navigate", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ZBUF_ORBIT);
+ RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_DEPTH_NAVIGATE);
RNA_def_property_ui_text(prop, "Auto Depth",
"Use the depth under the mouse to improve view pan/rotate/zoom functionality");
prop = RNA_def_property(srna, "use_mouse_depth_cursor", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ZBUF_CURSOR);
+ RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_DEPTH_CURSOR);
RNA_def_property_ui_text(prop, "Cursor Depth",
"Use the depth under the mouse when placing the cursor");
@@ -4216,7 +4219,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_text_antialiasing", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "text_render", USER_TEXT_DISABLE_AA);
RNA_def_property_ui_text(prop, "Text Anti-aliasing", "Draw user interface text anti-aliased");
- RNA_def_property_update(prop, 0, "rna_userdef_text_update");
+ RNA_def_property_update(prop, 0, "rna_userdef_text_antialiasing_update");
prop = RNA_def_property(srna, "select_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "gpu_select_method");
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index bcb5bb524f0..1d4652b0212 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -760,9 +760,8 @@ static void rna_workspace_screen_update(bContext *C, PointerRNA *ptr)
static PointerRNA rna_Window_view_layer_get(PointerRNA *ptr)
{
wmWindow *win = ptr->data;
- Scene *scene = WM_window_get_active_scene(win);
- WorkSpace *workspace = WM_window_get_active_workspace(win);
- ViewLayer *view_layer = BKE_workspace_view_layer_get(workspace, scene);
+ Scene *scene;
+ ViewLayer *view_layer = WM_window_get_active_view_layer_ex(win, &scene);
PointerRNA scene_ptr;
RNA_id_pointer_create(&scene->id, &scene_ptr);
@@ -778,28 +777,6 @@ static void rna_Window_view_layer_set(PointerRNA *ptr, PointerRNA value)
BKE_workspace_view_layer_set(workspace, value.data, scene);
}
-#ifdef USE_WORKSPACE_MODE
-
-static int rna_Window_object_mode_get(PointerRNA *ptr)
-{
- wmWindow *win = ptr->data;
- Scene *scene = WM_window_get_active_scene(win);
- WorkSpace *workspace = WM_window_get_active_workspace(win);
-
- return (int)BKE_workspace_object_mode_get(workspace, scene);
-}
-
-static void rna_Window_object_mode_set(PointerRNA *ptr, int value)
-{
- wmWindow *win = ptr->data;
- Scene *scene = WM_window_get_active_scene(win);
- WorkSpace *workspace = WM_window_get_active_workspace(win);
-
- BKE_workspace_object_mode_set(workspace, scene, value);
-}
-
-#endif /* USE_WORKSPACE_MODE */
-
static PointerRNA rna_KeyMapItem_properties_get(PointerRNA *ptr)
{
wmKeyMapItem *kmi = ptr->data;
@@ -2086,13 +2063,6 @@ static void rna_def_window(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL);
RNA_def_property_update(prop, NC_SCREEN | ND_LAYER, NULL);
-#ifdef USE_WORKSPACE_MODE
- prop = RNA_def_property(srna, "object_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, rna_enum_object_mode_items);
- RNA_def_property_enum_funcs(prop, "rna_Window_object_mode_get", "rna_Window_object_mode_set", NULL);
- RNA_def_property_ui_text(prop, "Mode", "Object interaction mode used in this window");
-#endif
-
prop = RNA_def_property(srna, "x", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "posx");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -2266,6 +2236,10 @@ static void rna_def_keyconfig(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Name", "Name of the key map");
RNA_def_struct_name_property(srna, prop);
+ prop = RNA_def_property(srna, "bl_owner_id", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "owner_id");
+ RNA_def_property_ui_text(prop, "Owner", "Internal owner");
+
prop = RNA_def_property(srna, "space_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "spaceid");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
diff --git a/source/blender/makesrna/intern/rna_wm_manipulator.c b/source/blender/makesrna/intern/rna_wm_manipulator.c
index d6de12407b0..bb40a12f5d5 100644
--- a/source/blender/makesrna/intern/rna_wm_manipulator.c
+++ b/source/blender/makesrna/intern/rna_wm_manipulator.c
@@ -806,6 +806,13 @@ static StructRNA *rna_ManipulatorGroup_register(
wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_append_ptr(
BPY_RNA_manipulatorgroup_wrapper, (void *)&dummywgt);
+ {
+ const char *owner_id = RNA_struct_state_owner_get();
+ if (owner_id) {
+ BLI_strncpy(wgt->owner_id, owner_id, sizeof(wgt->owner_id));
+ }
+ }
+
if (wgt->flag & WM_MANIPULATORGROUPTYPE_PERSISTENT) {
WM_manipulator_group_type_add_ptr_ex(wgt, mmap_type);
@@ -1204,6 +1211,10 @@ static void rna_def_manipulatorgroup(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_REGISTER);
RNA_def_property_ui_text(prop, "Region Type", "The region where the panel is going to be used in");
+ prop = RNA_def_property(srna, "bl_owner_id", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "type->owner_id");
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
/* bl_options */
static EnumPropertyItem manipulatorgroup_flag_items[] = {
{WM_MANIPULATORGROUPTYPE_3D, "3D", 0, "3D",
diff --git a/source/blender/makesrna/intern/rna_workspace.c b/source/blender/makesrna/intern/rna_workspace.c
index 0bed91f2807..609493c54b8 100644
--- a/source/blender/makesrna/intern/rna_workspace.c
+++ b/source/blender/makesrna/intern/rna_workspace.c
@@ -52,6 +52,10 @@
#include "RNA_access.h"
+static void rna_window_update_all(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+{
+ WM_main_add_notifier(NC_WINDOW, NULL);
+}
void rna_workspace_screens_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
@@ -79,8 +83,94 @@ static PointerRNA rna_workspace_transform_orientations_item_get(CollectionProper
return rna_pointer_inherit_refine(&iter->parent, &RNA_TransformOrientation, transform_orientation);
}
+/* workspace.owner_ids */
+
+static wmOwnerID *rna_WorkSpace_owner_ids_new(
+ WorkSpace *workspace, const char *name)
+{
+ wmOwnerID *owner_id = MEM_callocN(sizeof(*owner_id), __func__);
+ BLI_addtail(&workspace->owner_ids, owner_id);
+ BLI_strncpy(owner_id->name, name, sizeof(owner_id->name));
+ WM_main_add_notifier(NC_WINDOW, NULL);
+ return owner_id;
+}
+
+static void rna_WorkSpace_owner_ids_remove(
+ WorkSpace *workspace, ReportList *reports, PointerRNA *wstag_ptr)
+{
+ wmOwnerID *owner_id = wstag_ptr->data;
+ if (BLI_remlink_safe(&workspace->owner_ids, owner_id) == false) {
+ BKE_reportf(reports, RPT_ERROR,
+ "wmOwnerID '%s' not in workspace '%s'",
+ owner_id->name, workspace->id.name + 2);
+ return;
+ }
+
+ MEM_freeN(owner_id);
+ RNA_POINTER_INVALIDATE(wstag_ptr);
+
+ WM_main_add_notifier(NC_WINDOW, NULL);
+}
+
+static void rna_WorkSpace_owner_ids_clear(
+ WorkSpace *workspace)
+{
+ BLI_freelistN(&workspace->owner_ids);
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER | NA_REMOVED, workspace);
+}
+
#else /* RNA_RUNTIME */
+static void rna_def_workspace_owner(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "wmOwnerID", NULL);
+ RNA_def_struct_sdna(srna, "wmOwnerID");
+ RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
+ RNA_def_struct_ui_text(srna, "Work Space UI Tag", "");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "");
+ RNA_def_struct_name_property(srna, prop);
+}
+
+static void rna_def_workspace_owner_ids(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "wmOwnerIDs");
+ srna = RNA_def_struct(brna, "wmOwnerIDs", NULL);
+ RNA_def_struct_sdna(srna, "WorkSpace");
+ RNA_def_struct_ui_text(srna, "WorkSpace UI Tags", "");
+
+ /* add owner_id */
+ func = RNA_def_function(srna, "new", "rna_WorkSpace_owner_ids_new");
+ RNA_def_function_ui_description(func, "Add ui tag");
+ parm = RNA_def_string(func, "name", "Name", 0, "", "New name for the tag");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ /* return type */
+ parm = RNA_def_pointer(func, "owner_id", "wmOwnerID", "", "");
+ RNA_def_function_return(func, parm);
+
+ /* remove owner_id */
+ func = RNA_def_function(srna, "remove", "rna_WorkSpace_owner_ids_remove");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "Remove ui tag");
+ /* owner_id to remove */
+ parm = RNA_def_pointer(func, "owner_id", "wmOwnerID", "", "Tag to remove");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
+
+ /* clear all modifiers */
+ func = RNA_def_function(srna, "clear", "rna_WorkSpace_owner_ids_clear");
+ RNA_def_function_ui_description(func, "Remove all tags");
+}
+
static void rna_def_workspace(BlenderRNA *brna)
{
StructRNA *srna;
@@ -121,6 +211,17 @@ static void rna_def_workspace(BlenderRNA *brna)
"rna_workspace_transform_orientations_item_get", NULL, NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Transform Orientations", "");
+ prop = RNA_def_property(srna, "owner_ids", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "wmOwnerID");
+ RNA_def_property_ui_text(prop, "UI Tags", "");
+ rna_def_workspace_owner_ids(brna, prop);
+
+#if 0
+ prop = RNA_def_property(srna, "object_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_enum_object_mode_items);
+ RNA_def_property_ui_text(prop, "Mode", "Object interaction mode used in this window");
+#endif
+
/* View Render */
prop = RNA_def_property(srna, "view_render", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
@@ -134,6 +235,13 @@ static void rna_def_workspace(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Scene Settings",
"Use scene settings instead of workspace settings");
RNA_def_property_update(prop, NC_SCREEN | ND_LAYER, NULL);
+
+ prop = RNA_def_property(srna, "use_filter_by_owner", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", WORKSPACE_USE_FILTER_BY_ORIGIN);
+ RNA_def_property_ui_text(prop, "Use UI Tags",
+ "Filter the UI by tags");
+ RNA_def_property_update(prop, 0, "rna_window_update_all");
}
static void rna_def_transform_orientation(BlenderRNA *brna)
@@ -156,6 +264,7 @@ static void rna_def_transform_orientation(BlenderRNA *brna)
void RNA_def_workspace(BlenderRNA *brna)
{
+ rna_def_workspace_owner(brna);
rna_def_workspace(brna);
rna_def_transform_orientation(brna);
}
diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c
index 15fa686a40a..e78355ee426 100644
--- a/source/blender/makesrna/intern/rna_world.c
+++ b/source/blender/makesrna/intern/rna_world.c
@@ -396,9 +396,9 @@ static void rna_def_world_mist(BlenderRNA *brna)
PropertyRNA *prop;
static const EnumPropertyItem falloff_items[] = {
- {0, "QUADRATIC", 0, "Quadratic", "Use quadratic progression"},
- {1, "LINEAR", 0, "Linear", "Use linear progression"},
- {2, "INVERSE_QUADRATIC", 0, "Inverse Quadratic", "Use inverse quadratic progression"},
+ {WO_MIST_QUADRATIC, "QUADRATIC", 0, "Quadratic", "Use quadratic progression"},
+ {WO_MIST_LINEAR, "LINEAR", 0, "Linear", "Use linear progression"},
+ {WO_MIST_INVERSE_QUADRATIC, "INVERSE_QUADRATIC", 0, "Inverse Quadratic", "Use inverse quadratic progression"},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index 8066d0605fc..cf1021ec945 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -108,7 +108,6 @@ set(SRC
intern/MOD_wireframe.c
MOD_modifiertypes.h
- intern/MOD_boolean_util.h
intern/MOD_fluidsim_util.h
intern/MOD_meshcache_util.h
intern/MOD_util.h
@@ -122,16 +121,6 @@ if(WITH_ALEMBIC)
)
endif()
-if(WITH_MOD_BOOLEAN)
- add_definitions(-DWITH_MOD_BOOLEAN)
- list(APPEND SRC
- intern/MOD_boolean_util.c
- )
- list(APPEND INC
- ../../../extern/carve
- )
-endif()
-
if(WITH_MOD_REMESH)
add_definitions(-DWITH_MOD_REMESH)
list(APPEND INC
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index 60c7998853e..f6640704a83 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -97,16 +97,12 @@ static void foreachObjectLink(
walk(userData, ob, &amd->object, IDWALK_CB_NOP);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
ArmatureModifierData *amd = (ArmatureModifierData *)md;
if (amd->object != NULL) {
- DEG_add_object_relation(node, amd->object, DEG_OB_COMP_EVAL_POSE, "Armature Modifier");
- DEG_add_object_relation(node, amd->object, DEG_OB_COMP_TRANSFORM, "Armature Modifier");
+ DEG_add_object_relation(ctx->node, amd->object, DEG_OB_COMP_EVAL_POSE, "Armature Modifier");
+ DEG_add_object_relation(ctx->node, amd->object, DEG_OB_COMP_TRANSFORM, "Armature Modifier");
}
}
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 91501e539c0..f598667f96d 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -51,6 +51,7 @@
#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
+#include "BKE_object_deform.h"
#include "MOD_util.h"
@@ -96,26 +97,22 @@ static void foreachObjectLink(
walk(userData, ob, &amd->offset_ob, IDWALK_CB_NOP);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
ArrayModifierData *amd = (ArrayModifierData *)md;
if (amd->start_cap != NULL) {
- DEG_add_object_relation(node, amd->start_cap, DEG_OB_COMP_TRANSFORM, "Array Modifier Start Cap");
+ DEG_add_object_relation(ctx->node, amd->start_cap, DEG_OB_COMP_TRANSFORM, "Array Modifier Start Cap");
}
if (amd->end_cap != NULL) {
- DEG_add_object_relation(node, amd->end_cap, DEG_OB_COMP_TRANSFORM, "Array Modifier End Cap");
+ DEG_add_object_relation(ctx->node, amd->end_cap, DEG_OB_COMP_TRANSFORM, "Array Modifier End Cap");
}
if (amd->curve_ob) {
- struct Depsgraph *depsgraph = DEG_get_graph_from_handle(node);
- DEG_add_object_relation(node, amd->curve_ob, DEG_OB_COMP_GEOMETRY, "Array Modifier Curve");
+ struct Depsgraph *depsgraph = DEG_get_graph_from_handle(ctx->node);
+ DEG_add_object_relation(ctx->node, amd->curve_ob, DEG_OB_COMP_GEOMETRY, "Array Modifier Curve");
DEG_add_special_eval_flag(depsgraph, &amd->curve_ob->id, DAG_EVAL_NEED_CURVE_PATH);
}
if (amd->offset_ob != NULL) {
- DEG_add_object_relation(node, amd->offset_ob, DEG_OB_COMP_TRANSFORM, "Array Modifier Offset");
+ DEG_add_object_relation(ctx->node, amd->offset_ob, DEG_OB_COMP_TRANSFORM, "Array Modifier Offset");
}
}
@@ -279,7 +276,7 @@ static void dm_mvert_map_doubles(
static void dm_merge_transform(
DerivedMesh *result, DerivedMesh *cap_dm, float cap_offset[4][4],
unsigned int cap_verts_index, unsigned int cap_edges_index, int cap_loops_index, int cap_polys_index,
- int cap_nverts, int cap_nedges, int cap_nloops, int cap_npolys)
+ int cap_nverts, int cap_nedges, int cap_nloops, int cap_npolys, int *remap, int remap_len)
{
int *index_orig;
int i;
@@ -287,6 +284,7 @@ static void dm_merge_transform(
MEdge *me;
MLoop *ml;
MPoly *mp;
+ MDeformVert *dvert;
/* needed for subsurf so arrays are allocated */
cap_dm->getVertArray(cap_dm);
@@ -307,6 +305,12 @@ static void dm_merge_transform(
mv->flag = mv->bweight = 0;
}
+ /* remap the vertex groups if necessary */
+ dvert = DM_get_vert_data(result, cap_verts_index, CD_MDEFORMVERT);
+ if (dvert != NULL) {
+ BKE_object_defgroup_index_map_apply(dvert, cap_nverts, remap, remap_len);
+ }
+
/* adjust cap edge vertex indices */
me = CDDM_get_edges(result) + cap_edges_index;
for (i = 0; i < cap_nedges; i++, me++) {
@@ -383,6 +387,11 @@ static DerivedMesh *arrayModifier_doArray(
DerivedMesh *result, *start_cap_dm = NULL, *end_cap_dm = NULL;
+ int *vgroup_start_cap_remap = NULL;
+ int vgroup_start_cap_remap_len = 0;
+ int *vgroup_end_cap_remap = NULL;
+ int vgroup_end_cap_remap_len = 0;
+
chunk_nverts = dm->getNumVerts(dm);
chunk_nedges = dm->getNumEdges(dm);
chunk_nloops = dm->getNumLoops(dm);
@@ -391,6 +400,8 @@ static DerivedMesh *arrayModifier_doArray(
count = amd->count;
if (amd->start_cap && amd->start_cap != ob && amd->start_cap->type == OB_MESH) {
+ vgroup_start_cap_remap = BKE_object_defgroup_index_map_create(amd->start_cap, ob, &vgroup_start_cap_remap_len);
+
start_cap_dm = get_dm_for_modifier(amd->start_cap, flag);
if (start_cap_dm) {
start_cap_nverts = start_cap_dm->getNumVerts(start_cap_dm);
@@ -400,6 +411,8 @@ static DerivedMesh *arrayModifier_doArray(
}
}
if (amd->end_cap && amd->end_cap != ob && amd->end_cap->type == OB_MESH) {
+ vgroup_end_cap_remap = BKE_object_defgroup_index_map_create(amd->end_cap, ob, &vgroup_end_cap_remap_len);
+
end_cap_dm = get_dm_for_modifier(amd->end_cap, flag);
if (end_cap_dm) {
end_cap_nverts = end_cap_dm->getNumVerts(end_cap_dm);
@@ -656,7 +669,8 @@ static DerivedMesh *arrayModifier_doArray(
result_nedges - start_cap_nedges - end_cap_nedges,
result_nloops - start_cap_nloops - end_cap_nloops,
result_npolys - start_cap_npolys - end_cap_npolys,
- start_cap_nverts, start_cap_nedges, start_cap_nloops, start_cap_npolys);
+ start_cap_nverts, start_cap_nedges, start_cap_nloops, start_cap_npolys,
+ vgroup_start_cap_remap, vgroup_start_cap_remap_len);
/* Identify doubles with first chunk */
if (use_merge) {
dm_mvert_map_doubles(
@@ -680,7 +694,8 @@ static DerivedMesh *arrayModifier_doArray(
result_nedges - end_cap_nedges,
result_nloops - end_cap_nloops,
result_npolys - end_cap_npolys,
- end_cap_nverts, end_cap_nedges, end_cap_nloops, end_cap_npolys);
+ end_cap_nverts, end_cap_nedges, end_cap_nloops, end_cap_npolys,
+ vgroup_end_cap_remap, vgroup_end_cap_remap_len);
/* Identify doubles with last chunk */
if (use_merge) {
dm_mvert_map_doubles(
@@ -728,6 +743,13 @@ static DerivedMesh *arrayModifier_doArray(
result->dirty |= DM_DIRTY_NORMALS;
}
+ if (vgroup_start_cap_remap) {
+ MEM_freeN(vgroup_start_cap_remap);
+ }
+ if (vgroup_end_cap_remap) {
+ MEM_freeN(vgroup_end_cap_remap);
+ }
+
return result;
}
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index 0554fbb0317..c9d762a7fbe 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -33,10 +33,6 @@
*/
// #ifdef DEBUG_TIME
-#define USE_BMESH
-#ifdef WITH_MOD_BOOLEAN
-# define USE_CARVE WITH_MOD_BOOLEAN
-#endif
#include <stdio.h>
@@ -49,11 +45,9 @@
#include "BKE_library_query.h"
#include "BKE_modifier.h"
-#include "MOD_boolean_util.h"
#include "MOD_util.h"
-#ifdef USE_BMESH
#include "BLI_alloca.h"
#include "BLI_math_geom.h"
#include "BKE_material.h"
@@ -63,18 +57,16 @@
#include "bmesh.h"
#include "bmesh_tools.h"
#include "tools/bmesh_intersect.h"
-#endif
#ifdef DEBUG_TIME
-#include "PIL_time.h"
-#include "PIL_time_utildefines.h"
+# include "PIL_time.h"
+# include "PIL_time_utildefines.h"
#endif
static void initData(ModifierData *md)
{
BooleanModifierData *bmd = (BooleanModifierData *)md;
- bmd->solver = eBooleanModifierSolver_BMesh;
bmd->double_threshold = 1e-6f;
}
@@ -103,23 +95,17 @@ static void foreachObjectLink(
walk(userData, ob, &bmd->object, IDWALK_CB_NOP);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *ob,
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
BooleanModifierData *bmd = (BooleanModifierData *)md;
if (bmd->object != NULL) {
- DEG_add_object_relation(node, bmd->object, DEG_OB_COMP_TRANSFORM, "Boolean Modifier");
- DEG_add_object_relation(node, bmd->object, DEG_OB_COMP_GEOMETRY, "Boolean Modifier");
+ DEG_add_object_relation(ctx->node, bmd->object, DEG_OB_COMP_TRANSFORM, "Boolean Modifier");
+ DEG_add_object_relation(ctx->node, bmd->object, DEG_OB_COMP_GEOMETRY, "Boolean Modifier");
}
/* We need own transformation as well. */
- DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "Boolean Modifier");
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Boolean Modifier");
}
-#if defined(USE_CARVE) || defined(USE_BMESH)
-
static DerivedMesh *get_quick_derivedMesh(
Object *ob_self, DerivedMesh *dm_self,
Object *ob_other, DerivedMesh *dm_other,
@@ -166,13 +152,7 @@ static DerivedMesh *get_quick_derivedMesh(
return result;
}
-#endif /* defined(USE_CARVE) || defined(USE_BMESH) */
-
-/* -------------------------------------------------------------------- */
-/* BMESH */
-
-#ifdef USE_BMESH
/* has no meaning for faces, do this so we can tell which face is which */
#define BM_FACE_TAG BM_ELEM_DRAW
@@ -185,8 +165,8 @@ static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data))
return BM_elem_flag_test(f, BM_FACE_TAG) ? 1 : 0;
}
-static DerivedMesh *applyModifier_bmesh(
- ModifierData *md, Object *ob,
+static DerivedMesh *applyModifier(
+ ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob,
DerivedMesh *dm,
ModifierApplyFlag flag)
{
@@ -354,66 +334,6 @@ static DerivedMesh *applyModifier_bmesh(
return dm;
}
-#endif /* USE_BMESH */
-
-
-/* -------------------------------------------------------------------- */
-/* CARVE */
-
-#ifdef USE_CARVE
-static DerivedMesh *applyModifier_carve(
- ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
- ModifierApplyFlag flag)
-{
- BooleanModifierData *bmd = (BooleanModifierData *) md;
- DerivedMesh *dm;
-
- if (!bmd->object)
- return derivedData;
-
- dm = get_dm_for_modifier(bmd->object, flag);
-
- if (dm) {
- DerivedMesh *result;
-
- /* when one of objects is empty (has got no faces) we could speed up
- * calculation a bit returning one of objects' derived meshes (or empty one)
- * Returning mesh is depended on modifiers operation (sergey) */
- result = get_quick_derivedMesh(ob, derivedData, bmd->object, dm, bmd->operation);
-
- if (result == NULL) {
-#ifdef DEBUG_TIME
- TIMEIT_START(boolean_carve);
-#endif
-
- result = NewBooleanDerivedMesh(dm, bmd->object, derivedData, ob,
- 1 + bmd->operation);
-#ifdef DEBUG_TIME
- TIMEIT_END(boolean_carve);
-#endif
- }
-
- /* if new mesh returned, return it; otherwise there was
- * an error, so delete the modifier object */
- if (result)
- return result;
- else
- modifier_setError(md, "Cannot execute boolean operation");
- }
-
- return derivedData;
-}
-#endif /* USE_CARVE */
-
-
-static DerivedMesh *applyModifier_nop(
- ModifierData *UNUSED(md), Object *UNUSED(ob),
- DerivedMesh *derivedData,
- ModifierApplyFlag UNUSED(flag))
-{
- return derivedData;
-}
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md))
{
@@ -424,28 +344,6 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(
return dataMask;
}
-static DerivedMesh *applyModifier(
- ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
- Object *ob, DerivedMesh *derivedData,
- ModifierApplyFlag flag)
-{
- BooleanModifierData *bmd = (BooleanModifierData *)md;
-
- switch (bmd->solver) {
-#ifdef USE_CARVE
- case eBooleanModifierSolver_Carve:
- return applyModifier_carve(md, ob, derivedData, flag);
-#endif
-#ifdef USE_BMESH
- case eBooleanModifierSolver_BMesh:
- return applyModifier_bmesh(md, ob, derivedData, flag);
-#endif
- default:
- return applyModifier_nop(md, ob, derivedData, flag);
- }
-}
-
-
ModifierTypeInfo modifierType_Boolean = {
/* name */ "Boolean",
/* structName */ "BooleanModifierData",
diff --git a/source/blender/modifiers/intern/MOD_boolean_util.c b/source/blender/modifiers/intern/MOD_boolean_util.c
deleted file mode 100644
index 49010664aa8..00000000000
--- a/source/blender/modifiers/intern/MOD_boolean_util.c
+++ /dev/null
@@ -1,790 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) Blender Foundation
- * All rights reserved.
- *
- * Contributor(s): Sergey Sharybin.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/modifiers/intern/MOD_boolean_util.c
- * \ingroup modifiers
- */
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_material_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_object_types.h"
-
-#include "BLI_utildefines.h"
-#include "BLI_alloca.h"
-#include "BLI_ghash.h"
-#include "BLI_math.h"
-
-#include "BKE_cdderivedmesh.h"
-#include "BKE_material.h"
-
-#include "MOD_boolean_util.h"
-
-#include "carve-capi.h"
-
-/* Adopted from BM_loop_interp_from_face(),
- *
- * Transform matrix is used in cases when target coordinate needs
- * to be converted to source space (namely when interpolating
- * boolean result loops from second operand).
- *
- * TODO(sergey): Consider making it a generic function in DerivedMesh.c.
- */
-static void DM_loop_interp_from_poly(DerivedMesh *source_dm,
- MVert *source_mverts,
- MLoop *source_mloops,
- MPoly *source_poly,
- DerivedMesh *target_dm,
- MVert *target_mverts,
- MLoop *target_mloop,
- float transform[4][4],
- int target_loop_index)
-{
- float (*cos_3d)[3] = BLI_array_alloca(cos_3d, source_poly->totloop);
- int *source_indices = BLI_array_alloca(source_indices, source_poly->totloop);
- float *weights = BLI_array_alloca(weights, source_poly->totloop);
- int i;
- int target_vert_index = target_mloop[target_loop_index].v;
- float coord[3];
-
- for (i = 0; i < source_poly->totloop; ++i) {
- MLoop *mloop = &source_mloops[source_poly->loopstart + i];
- source_indices[i] = source_poly->loopstart + i;
- copy_v3_v3(cos_3d[i], source_mverts[mloop->v].co);
- }
-
- if (transform) {
- mul_v3_m4v3(coord, transform, target_mverts[target_vert_index].co);
- }
- else {
- copy_v3_v3(coord, target_mverts[target_vert_index].co);
- }
-
- interp_weights_poly_v3(weights, cos_3d, source_poly->totloop, coord);
-
- DM_interp_loop_data(source_dm, target_dm, source_indices, weights,
- source_poly->totloop, target_loop_index);
-}
-
-typedef struct DMArrays {
- MVert *mvert;
- MEdge *medge;
- MLoop *mloop;
- MPoly *mpoly;
- bool mvert_allocated;
- bool medge_allocated;
- bool mloop_allocated;
- bool mpoly_allocated;
-} DMArrays;
-
-static void dm_arrays_get(DerivedMesh *dm, DMArrays *arrays)
-{
- arrays->mvert = DM_get_vert_array(dm, &arrays->mvert_allocated);
- arrays->medge = DM_get_edge_array(dm, &arrays->medge_allocated);
- arrays->mloop = DM_get_loop_array(dm, &arrays->mloop_allocated);
- arrays->mpoly = DM_get_poly_array(dm, &arrays->mpoly_allocated);
-}
-
-static void dm_arrays_free(DMArrays *arrays)
-{
- if (arrays->mvert_allocated) {
- MEM_freeN(arrays->mvert);
- }
- if (arrays->medge_allocated) {
- MEM_freeN(arrays->medge);
- }
- if (arrays->mloop_allocated) {
- MEM_freeN(arrays->mloop);
- }
- if (arrays->mpoly_allocated) {
- MEM_freeN(arrays->mpoly);
- }
-}
-
-/* **** Importer from derived mesh to Carve **** */
-
-typedef struct ImportMeshData {
- DerivedMesh *dm;
- float obmat[4][4];
- MVert *mvert;
- MEdge *medge;
- MLoop *mloop;
- MPoly *mpoly;
-} ImportMeshData;
-
-/* Get number of vertices. */
-static int importer_GetNumVerts(ImportMeshData *import_data)
-{
- DerivedMesh *dm = import_data->dm;
- return dm->getNumVerts(dm);
-}
-
-/* Get number of edges. */
-static int importer_GetNumEdges(ImportMeshData *import_data)
-{
- DerivedMesh *dm = import_data->dm;
- return dm->getNumEdges(dm);
-}
-
-/* Get number of loops. */
-static int importer_GetNumLoops(ImportMeshData *import_data)
-{
- DerivedMesh *dm = import_data->dm;
- return dm->getNumLoops(dm);
-}
-
-/* Get number of polys. */
-static int importer_GetNumPolys(ImportMeshData *import_data)
-{
- DerivedMesh *dm = import_data->dm;
- return dm->getNumPolys(dm);
-}
-
-/* Get 3D coordinate of vertex with given index. */
-static void importer_GetVertCoord(ImportMeshData *import_data, int vert_index, float coord[3])
-{
- MVert *mvert = import_data->mvert;
-
- BLI_assert(vert_index >= 0 && vert_index < import_data->dm->getNumVerts(import_data->dm));
-
- mul_v3_m4v3(coord, import_data->obmat, mvert[vert_index].co);
-}
-
-/* Get index of vertices which are adjucent to edge specified by it's index. */
-static void importer_GetEdgeVerts(ImportMeshData *import_data, int edge_index, int *v1, int *v2)
-{
- MEdge *medge = &import_data->medge[edge_index];
-
- BLI_assert(edge_index >= 0 && edge_index < import_data->dm->getNumEdges(import_data->dm));
-
- *v1 = medge->v1;
- *v2 = medge->v2;
-}
-
-/* Get number of adjucent vertices to the poly specified by it's index. */
-static int importer_GetPolyNumVerts(ImportMeshData *import_data, int poly_index)
-{
- MPoly *mpoly = import_data->mpoly;
-
- BLI_assert(poly_index >= 0 && poly_index < import_data->dm->getNumPolys(import_data->dm));
-
- return mpoly[poly_index].totloop;
-}
-
-/* Get list of adjucent vertices to the poly specified by it's index. */
-static void importer_GetPolyVerts(ImportMeshData *import_data, int poly_index, int *verts)
-{
- MPoly *mpoly = &import_data->mpoly[poly_index];
- MLoop *mloop = import_data->mloop + mpoly->loopstart;
- int i;
- BLI_assert(poly_index >= 0 && poly_index < import_data->dm->getNumPolys(import_data->dm));
- for (i = 0; i < mpoly->totloop; i++, mloop++) {
- verts[i] = mloop->v;
- }
-}
-
-// Triangulate 2D polygon.
-#if 0
-static int importer_triangulate2DPoly(ImportMeshData *UNUSED(import_data),
- const float (*vertices)[2], int num_vertices,
- unsigned int (*triangles)[3])
-{
- // TODO(sergey): Currently import_data is unused but in the future we could
- // put memory arena there which will reduce amount of allocations happening
- // over the triangulation period.
- //
- // However that's not so much straighforward to do it right now because we
- // also are tu consider threaded import/export.
-
- BLI_assert(num_vertices > 3);
-
- BLI_polyfill_calc(vertices, num_vertices, triangles);
-
- return num_vertices - 2;
-}
-#endif
-
-static CarveMeshImporter MeshImporter = {
- importer_GetNumVerts,
- importer_GetNumEdges,
- importer_GetNumLoops,
- importer_GetNumPolys,
- importer_GetVertCoord,
- importer_GetEdgeVerts,
- importer_GetPolyNumVerts,
- importer_GetPolyVerts,
-
- /* TODO(sergey): We don't use BLI_polyfill_calc() because it tends
- * to generate degenerated geometry which is fatal for booleans.
- *
- * For now we stick to Carve's triangulation.
- */
- NULL, /* importer_triangulate2DPoly */
-};
-
-/* **** Exporter from Carve to derived mesh **** */
-
-typedef struct ExportMeshData {
- DerivedMesh *dm;
- float obimat[4][4];
- MVert *mvert;
- MEdge *medge;
- MLoop *mloop;
- MPoly *mpoly;
- int *vert_origindex;
- int *edge_origindex;
- int *poly_origindex;
- int *loop_origindex;
-
- /* Objects and derived meshes of left and right operands.
- * Used for custom data merge and interpolation.
- */
- Object *ob_left;
- Object *ob_right;
- DerivedMesh *dm_left;
- DerivedMesh *dm_right;
- MVert *mvert_left;
- MEdge *medge_left;
- MLoop *mloop_left;
- MPoly *mpoly_left;
- MVert *mvert_right;
- MEdge *medge_right;
- MLoop *mloop_right;
- MPoly *mpoly_right;
-
- float left_to_right_mat[4][4];
-
- /* Hash to map materials from right object to result. */
- GHash *material_hash;
-} ExportMeshData;
-
-BLI_INLINE Object *which_object(ExportMeshData *export_data, int which_mesh)
-{
- Object *object = NULL;
- switch (which_mesh) {
- case CARVE_MESH_LEFT:
- object = export_data->ob_left;
- break;
- case CARVE_MESH_RIGHT:
- object = export_data->ob_right;
- break;
- }
- return object;
-}
-
-BLI_INLINE DerivedMesh *which_dm(ExportMeshData *export_data, int which_mesh)
-{
- DerivedMesh *dm = NULL;
- switch (which_mesh) {
- case CARVE_MESH_LEFT:
- dm = export_data->dm_left;
- break;
- case CARVE_MESH_RIGHT:
- dm = export_data->dm_right;
- break;
- }
- return dm;
-}
-
-BLI_INLINE MVert *which_mvert(ExportMeshData *export_data, int which_mesh)
-{
- MVert *mvert = NULL;
- switch (which_mesh) {
- case CARVE_MESH_LEFT:
- mvert = export_data->mvert_left;
- break;
- case CARVE_MESH_RIGHT:
- mvert = export_data->mvert_right;
- break;
- }
- return mvert;
-}
-
-BLI_INLINE MEdge *which_medge(ExportMeshData *export_data, int which_mesh)
-{
- MEdge *medge = NULL;
- switch (which_mesh) {
- case CARVE_MESH_LEFT:
- medge = export_data->medge_left;
- break;
- case CARVE_MESH_RIGHT:
- medge = export_data->medge_right;
- break;
- }
- return medge;
-}
-
-BLI_INLINE MLoop *which_mloop(ExportMeshData *export_data, int which_mesh)
-{
- MLoop *mloop = NULL;
- switch (which_mesh) {
- case CARVE_MESH_LEFT:
- mloop = export_data->mloop_left;
- break;
- case CARVE_MESH_RIGHT:
- mloop = export_data->mloop_right;
- break;
- }
- return mloop;
-}
-
-BLI_INLINE MPoly *which_mpoly(ExportMeshData *export_data, int which_mesh)
-{
- MPoly *mpoly = NULL;
- switch (which_mesh) {
- case CARVE_MESH_LEFT:
- mpoly = export_data->mpoly_left;
- break;
- case CARVE_MESH_RIGHT:
- mpoly = export_data->mpoly_right;
- break;
- }
- return mpoly;
-}
-
-/* Create new external mesh */
-static void exporter_InitGeomArrays(ExportMeshData *export_data,
- int num_verts, int num_edges,
- int num_loops, int num_polys)
-{
- DerivedMesh *dm = CDDM_new(num_verts, num_edges, 0,
- num_loops, num_polys);
- DerivedMesh *dm_left = export_data->dm_left,
- *dm_right = export_data->dm_right;
-
- /* Mask for custom data layers to be merged from operands. */
- CustomDataMask merge_mask = CD_MASK_DERIVEDMESH & ~CD_MASK_ORIGINDEX;
-
- export_data->dm = dm;
- export_data->mvert = dm->getVertArray(dm);
- export_data->medge = dm->getEdgeArray(dm);
- export_data->mloop = dm->getLoopArray(dm);
- export_data->mpoly = dm->getPolyArray(dm);
-
- /* Merge custom data layers from operands.
- *
- * Will only create custom data layers for all the layers which appears in
- * the operand. Data for those layers will not be allocated or initialized.
- */
-
- CustomData_merge(&dm_left->vertData, &dm->vertData, merge_mask, CD_DEFAULT, num_verts);
- CustomData_merge(&dm_right->vertData, &dm->vertData, merge_mask, CD_DEFAULT, num_verts);
-
- CustomData_merge(&dm_left->loopData, &dm->loopData, merge_mask, CD_DEFAULT, num_loops);
- CustomData_merge(&dm_right->loopData, &dm->loopData, merge_mask, CD_DEFAULT, num_loops);
-
- CustomData_merge(&dm_left->polyData, &dm->polyData, merge_mask, CD_DEFAULT, num_polys);
- CustomData_merge(&dm_right->polyData, &dm->polyData, merge_mask, CD_DEFAULT, num_polys);
-
- CustomData_merge(&dm_left->edgeData, &dm->edgeData, merge_mask, CD_DEFAULT, num_edges);
- CustomData_merge(&dm_right->edgeData, &dm->edgeData, merge_mask, CD_DEFAULT, num_edges);
-
- export_data->vert_origindex = dm->getVertDataArray(dm, CD_ORIGINDEX);
- export_data->edge_origindex = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
- export_data->poly_origindex = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- export_data->loop_origindex = dm->getLoopDataArray(dm, CD_ORIGINDEX);
-}
-
-/* Set coordinate of vertex with given index. */
-static void exporter_SetVert(ExportMeshData *export_data,
- int vert_index, float coord[3],
- int which_orig_mesh, int orig_vert_index)
-{
- DerivedMesh *dm = export_data->dm;
- DerivedMesh *dm_orig;
- MVert *mvert = export_data->mvert;
-
- BLI_assert(vert_index >= 0 && vert_index <= dm->getNumVerts(dm));
-
- dm_orig = which_dm(export_data, which_orig_mesh);
- if (dm_orig) {
- BLI_assert(orig_vert_index >= 0 && orig_vert_index < dm_orig->getNumVerts(dm_orig));
- mvert[vert_index] = which_mvert(export_data, which_orig_mesh)[orig_vert_index];
- CustomData_copy_data(&dm_orig->vertData, &dm->vertData, orig_vert_index, vert_index, 1);
- }
-
- /* Set original index of the vertex. */
- if (export_data->vert_origindex) {
- if (which_orig_mesh == CARVE_MESH_LEFT) {
- export_data->vert_origindex[vert_index] = orig_vert_index;
- }
- else {
- export_data->vert_origindex[vert_index] = ORIGINDEX_NONE;
- }
- }
-
- mul_v3_m4v3(mvert[vert_index].co, export_data->obimat, coord);
-}
-
-/* Set vertices which are adjucent to the edge specified by it's index. */
-static void exporter_SetEdge(ExportMeshData *export_data,
- int edge_index, int v1, int v2,
- int which_orig_mesh, int orig_edge_index)
-{
- DerivedMesh *dm = export_data->dm;
- MEdge *medge = &export_data->medge[edge_index];
- DerivedMesh *dm_orig;
-
- BLI_assert(edge_index >= 0 && edge_index < dm->getNumEdges(dm));
- BLI_assert(v1 >= 0 && v1 < dm->getNumVerts(dm));
- BLI_assert(v2 >= 0 && v2 < dm->getNumVerts(dm));
-
- dm_orig = which_dm(export_data, which_orig_mesh);
- if (dm_orig) {
- BLI_assert(orig_edge_index >= 0 && orig_edge_index < dm_orig->getNumEdges(dm_orig));
-
- *medge = which_medge(export_data, which_orig_mesh)[orig_edge_index];
-
- /* Copy all edge layers, including medge. */
- CustomData_copy_data(&dm_orig->edgeData, &dm->edgeData, orig_edge_index, edge_index, 1);
- }
-
- /* Set original index of the edge. */
- if (export_data->edge_origindex) {
- if (which_orig_mesh == CARVE_MESH_LEFT) {
- export_data->edge_origindex[edge_index] = orig_edge_index;
- }
- else {
- export_data->edge_origindex[edge_index] = ORIGINDEX_NONE;
- }
- }
-
- medge->v1 = v1;
- medge->v2 = v2;
-
- medge->flag |= ME_EDGEDRAW | ME_EDGERENDER;
-}
-
-static void setMPolyMaterial(ExportMeshData *export_data,
- MPoly *mpoly,
- int which_orig_mesh)
-{
- Object *orig_object;
- GHash *material_hash;
- Material *orig_mat;
-
- if (which_orig_mesh == CARVE_MESH_LEFT) {
- /* No need to change materian index for faces from left operand */
- return;
- }
-
- material_hash = export_data->material_hash;
- orig_object = which_object(export_data, which_orig_mesh);
-
- /* Set material, based on lookup in hash table. */
- orig_mat = give_current_material(orig_object, mpoly->mat_nr + 1);
-
- if (orig_mat) {
- /* For faces from right operand check if there's requested material
- * in the left operand. And if it is, use index of that material,
- * otherwise fallback to first material (material with index=0).
- */
- if (!BLI_ghash_haskey(material_hash, orig_mat)) {
- int a, mat_nr;
-
- mat_nr = 0;
- for (a = 0; a < export_data->ob_left->totcol; a++) {
- if (give_current_material(export_data->ob_left, a + 1) == orig_mat) {
- mat_nr = a;
- break;
- }
- }
-
- BLI_ghash_insert(material_hash, orig_mat, SET_INT_IN_POINTER(mat_nr));
-
- mpoly->mat_nr = mat_nr;
- }
- else
- mpoly->mat_nr = GET_INT_FROM_POINTER(BLI_ghash_lookup(material_hash, orig_mat));
- }
- else {
- mpoly->mat_nr = 0;
- }
-}
-
-/* Set list of adjucent loops to the poly specified by it's index. */
-static void exporter_SetPoly(ExportMeshData *export_data,
- int poly_index, int start_loop, int num_loops,
- int which_orig_mesh, int orig_poly_index)
-{
- DerivedMesh *dm = export_data->dm;
- MPoly *mpoly = &export_data->mpoly[poly_index];
- DerivedMesh *dm_orig;
- int i;
-
- /* Poly is always to be either from left or right operand. */
- dm_orig = which_dm(export_data, which_orig_mesh);
-
- BLI_assert(poly_index >= 0 && poly_index < dm->getNumPolys(dm));
- BLI_assert(start_loop >= 0 && start_loop <= dm->getNumLoops(dm) - num_loops);
- BLI_assert(num_loops >= 3);
- BLI_assert(dm_orig != NULL);
- BLI_assert(orig_poly_index >= 0 && orig_poly_index < dm_orig->getNumPolys(dm_orig));
-
- /* Copy all poly layers, including mpoly. */
- *mpoly = which_mpoly(export_data, which_orig_mesh)[orig_poly_index];
- CustomData_copy_data(&dm_orig->polyData, &dm->polyData, orig_poly_index, poly_index, 1);
-
- /* Set material of the curren poly.
- * This would re-map materials from right operand to materials from the
- * left one as well.
- */
- setMPolyMaterial(export_data, mpoly, which_orig_mesh);
-
- /* Set original index of the poly. */
- if (export_data->poly_origindex) {
- if (which_orig_mesh == CARVE_MESH_LEFT) {
- export_data->poly_origindex[poly_index] = orig_poly_index;
- }
- else {
- export_data->poly_origindex[poly_index] = ORIGINDEX_NONE;
- }
- }
-
- /* Set poly data itself. */
- mpoly->loopstart = start_loop;
- mpoly->totloop = num_loops;
-
- /* Interpolate data for poly loops. */
- {
- MVert *source_mverts = which_mvert(export_data, which_orig_mesh);
- MLoop *source_mloops = which_mloop(export_data, which_orig_mesh);
- MPoly *source_mpolys = which_mpoly(export_data, which_orig_mesh);
- MPoly *source_poly = &source_mpolys[orig_poly_index];
- MVert *target_mverts = export_data->mvert;
- MLoop *target_mloops = export_data->mloop;
- float (*transform)[4] = NULL;
-
- if (which_orig_mesh == CARVE_MESH_RIGHT) {
- transform = export_data->left_to_right_mat;
- }
-
- for (i = 0; i < mpoly->totloop; i++) {
- DM_loop_interp_from_poly(dm_orig,
- source_mverts,
- source_mloops,
- source_poly,
- dm,
- target_mverts,
- target_mloops,
- transform,
- i + mpoly->loopstart);
- }
- }
-}
-
-/* Set list vertex and edge which are adjucent to loop with given index. */
-static void exporter_SetLoop(ExportMeshData *export_data,
- int loop_index, int vertex, int edge,
- int which_orig_mesh, int orig_loop_index)
-{
- DerivedMesh *dm = export_data->dm;
- MLoop *mloop = &export_data->mloop[loop_index];
- DerivedMesh *dm_orig;
-
- BLI_assert(loop_index >= 0 && loop_index < dm->getNumLoops(dm));
- BLI_assert(vertex >= 0 && vertex < dm->getNumVerts(dm));
- BLI_assert(edge >= 0 && vertex < dm->getNumEdges(dm));
-
- dm_orig = which_dm(export_data, which_orig_mesh);
- if (dm_orig) {
- BLI_assert(orig_loop_index >= 0 && orig_loop_index < dm_orig->getNumLoops(dm_orig));
-
- /* Copy all loop layers, including mloop. */
- *mloop = which_mloop(export_data, which_orig_mesh)[orig_loop_index];
- CustomData_copy_data(&dm_orig->loopData, &dm->loopData, orig_loop_index, loop_index, 1);
- }
-
- /* Set original index of the loop. */
- if (export_data->loop_origindex) {
- if (which_orig_mesh == CARVE_MESH_LEFT) {
- export_data->loop_origindex[loop_index] = orig_loop_index;
- }
- else {
- export_data->loop_origindex[loop_index] = ORIGINDEX_NONE;
- }
- }
-
- mloop->v = vertex;
- mloop->e = edge;
-}
-
-/* Edge index from a loop index for a given original mesh. */
-static int exporter_MapLoopToEdge(ExportMeshData *export_data,
- int which_mesh, int loop_index)
-{
- DerivedMesh *dm = which_dm(export_data, which_mesh);
- MLoop *mloop = which_mloop(export_data, which_mesh);
-
- (void) dm; /* Unused in release builds. */
-
- BLI_assert(dm != NULL);
- BLI_assert(loop_index >= 0 && loop_index < dm->getNumLoops(dm));
-
- return mloop[loop_index].e;
-}
-
-static CarveMeshExporter MeshExporter = {
- exporter_InitGeomArrays,
- exporter_SetVert,
- exporter_SetEdge,
- exporter_SetPoly,
- exporter_SetLoop,
- exporter_MapLoopToEdge
-};
-
-static int operation_from_optype(int int_op_type)
-{
- int operation;
-
- switch (int_op_type) {
- case 1:
- operation = CARVE_OP_INTERSECTION;
- break;
- case 2:
- operation = CARVE_OP_UNION;
- break;
- case 3:
- operation = CARVE_OP_A_MINUS_B;
- break;
- default:
- BLI_assert(!"Should not happen");
- operation = -1;
- break;
- }
-
- return operation;
-}
-
-static void prepare_import_data(Object *object,
- DerivedMesh *dm,
- const DMArrays *dm_arrays,
- ImportMeshData *import_data)
-{
- import_data->dm = dm;
- copy_m4_m4(import_data->obmat, object->obmat);
- import_data->mvert = dm_arrays->mvert;
- import_data->medge = dm_arrays->medge;
- import_data->mloop = dm_arrays->mloop;
- import_data->mpoly = dm_arrays->mpoly;
-}
-
-static struct CarveMeshDescr *carve_mesh_from_dm(Object *object,
- DerivedMesh *dm,
- const DMArrays *dm_arrays)
-{
- ImportMeshData import_data;
- prepare_import_data(object, dm, dm_arrays, &import_data);
- return carve_addMesh(&import_data, &MeshImporter);
-}
-
-static void prepare_export_data(Object *object_left, DerivedMesh *dm_left, const DMArrays *dm_left_arrays,
- Object *object_right, DerivedMesh *dm_right, const DMArrays *dm_right_arrays,
- ExportMeshData *export_data)
-{
- float object_right_imat[4][4];
-
- invert_m4_m4(export_data->obimat, object_left->obmat);
-
- export_data->ob_left = object_left;
- export_data->ob_right = object_right;
-
- export_data->dm_left = dm_left;
- export_data->dm_right = dm_right;
-
- export_data->mvert_left = dm_left_arrays->mvert;
- export_data->medge_left = dm_left_arrays->medge;
- export_data->mloop_left = dm_left_arrays->mloop;
- export_data->mpoly_left = dm_left_arrays->mpoly;
- export_data->mvert_right = dm_right_arrays->mvert;
- export_data->medge_right = dm_right_arrays->medge;
- export_data->mloop_right = dm_right_arrays->mloop;
- export_data->mpoly_right = dm_right_arrays->mpoly;
-
- export_data->material_hash = BLI_ghash_ptr_new("CSG_mat gh");
-
- /* Matrix to convert coord from left object's loca; space to
- * right object's local space.
- */
- invert_m4_m4(object_right_imat, object_right->obmat);
- mul_m4_m4m4(export_data->left_to_right_mat, object_left->obmat,
- object_right_imat);
-}
-
-DerivedMesh *NewBooleanDerivedMesh(DerivedMesh *dm, struct Object *ob,
- DerivedMesh *dm_select, struct Object *ob_select,
- int int_op_type)
-{
-
- struct CarveMeshDescr *left, *right, *output = NULL;
- DerivedMesh *output_dm = NULL;
- int operation;
- bool result;
- DMArrays dm_left_arrays, dm_right_arrays;
-
- if (dm == NULL || dm_select == NULL) {
- return NULL;
- }
-
- operation = operation_from_optype(int_op_type);
- if (operation == -1) {
- return NULL;
- }
-
- dm_arrays_get(dm_select, &dm_left_arrays);
- dm_arrays_get(dm, &dm_right_arrays);
-
- left = carve_mesh_from_dm(ob_select, dm_select, &dm_left_arrays);
- right = carve_mesh_from_dm(ob, dm, &dm_right_arrays);
-
- result = carve_performBooleanOperation(left, right, operation, &output);
-
- carve_deleteMesh(left);
- carve_deleteMesh(right);
-
- if (result) {
- ExportMeshData export_data;
-
- prepare_export_data(ob_select, dm_select, &dm_left_arrays,
- ob, dm, &dm_right_arrays,
- &export_data);
-
- carve_exportMesh(output, &MeshExporter, &export_data);
- output_dm = export_data.dm;
-
- /* Free memory used by export mesh. */
- BLI_ghash_free(export_data.material_hash, NULL, NULL);
-
- output_dm->cd_flag |= dm->cd_flag | dm_select->cd_flag;
- output_dm->dirty |= DM_DIRTY_NORMALS;
- carve_deleteMesh(output);
- }
-
- dm_arrays_free(&dm_left_arrays);
- dm_arrays_free(&dm_right_arrays);
-
- return output_dm;
-}
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index 7a52ede8838..2e0b13b0603 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -154,7 +154,7 @@ static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationConte
numLoops_dst += mp->totloop;
}
- BLI_assert(hash_num == BLI_ghash_size(vertHash));
+ BLI_assert(hash_num == BLI_ghash_len(vertHash));
/* get the set of edges that will be in the new mesh (i.e. all edges
* that have both verts in the new mesh)
@@ -187,7 +187,7 @@ static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationConte
*/
medge = medge_src;
hash_num = 0;
- BLI_assert(hash_num == BLI_ghash_size(vertHash));
+ BLI_assert(hash_num == BLI_ghash_len(vertHash));
for (i = 0; i < numEdges_dst; i++) {
void **val_p;
me = medge + edgeMap[i];
@@ -201,11 +201,11 @@ static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationConte
hash_num++;
}
}
- BLI_assert(hash_num == BLI_ghash_size(vertHash));
+ BLI_assert(hash_num == BLI_ghash_len(vertHash));
/* get the set of edges that will be in the new mesh */
for (i = 0; i < numEdges_dst; i++) {
- j = BLI_ghash_size(edgeHash);
+ j = BLI_ghash_len(edgeHash);
BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(j),
SET_INT_IN_POINTER(edgeMap[i]));
@@ -232,8 +232,8 @@ static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationConte
/* now we know the number of verts, edges and faces, we can create
* the mesh
*/
- result = CDDM_from_template(dm, BLI_ghash_size(vertHash),
- BLI_ghash_size(edgeHash), 0, numLoops_dst, numFaces_dst);
+ result = CDDM_from_template(dm, BLI_ghash_len(vertHash),
+ BLI_ghash_len(edgeHash), 0, numLoops_dst, numFaces_dst);
/* copy the vertices across */
GHASH_ITER (gh_iter, vertHash) {
@@ -250,7 +250,7 @@ static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationConte
}
/* copy the edges across, remapping indices */
- for (i = 0; i < BLI_ghash_size(edgeHash); i++) {
+ for (i = 0; i < BLI_ghash_len(edgeHash); i++) {
MEdge source;
MEdge *dest;
int oldIndex = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_INT_IN_POINTER(i)));
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
index 93a5b9607bf..bf86377960a 100644
--- a/source/blender/modifiers/intern/MOD_cast.c
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -102,16 +102,12 @@ static void foreachObjectLink(
walk(userData, ob, &cmd->object, IDWALK_CB_NOP);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *object,
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
CastModifierData *cmd = (CastModifierData *)md;
if (cmd->object != NULL) {
- DEG_add_object_relation(node, cmd->object, DEG_OB_COMP_TRANSFORM, "Cast Modifier");
- DEG_add_object_relation(node, object, DEG_OB_COMP_TRANSFORM, "Cast Modifier");
+ DEG_add_object_relation(ctx->node, cmd->object, DEG_OB_COMP_TRANSFORM, "Cast Modifier");
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Cast Modifier");
}
}
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index b234cc63228..0c55d8f8beb 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -114,18 +114,14 @@ static void deformVerts(ModifierData *md, const struct EvaluationContext *eval_c
dm->release(dm);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *scene,
- Object *ob,
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
ClothModifierData *clmd = (ClothModifierData *)md;
if (clmd != NULL) {
/* Actual code uses get_collisionobjects */
- DEG_add_collision_relations(node, scene, ob, clmd->coll_parms->group, eModifierType_Collision, NULL, true, "Cloth Collision");
+ DEG_add_collision_relations(ctx->node, ctx->scene, ctx->object, clmd->coll_parms->group, eModifierType_Collision, NULL, true, "Cloth Collision");
- DEG_add_forcefield_relations(node, scene, ob, clmd->sim_parms->effector_weights, true, 0, "Cloth Field");
+ DEG_add_forcefield_relations(ctx->node, ctx->scene, ctx->object, clmd->sim_parms->effector_weights, true, 0, "Cloth Field");
}
}
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index 62c9f8796a0..acb69de1e85 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -93,11 +93,7 @@ static void foreachObjectLink(
walk(userData, ob, &cmd->object, IDWALK_CB_NOP);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *object,
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
CurveModifierData *cmd = (CurveModifierData *)md;
if (cmd->object != NULL) {
@@ -107,12 +103,12 @@ static void updateDepsgraph(ModifierData *md,
/* TODO(sergey): Currently path is evaluated as a part of modifier stack,
* might be changed in the future.
*/
- struct Depsgraph *depsgraph = DEG_get_graph_from_handle(node);
- DEG_add_object_relation(node, cmd->object, DEG_OB_COMP_GEOMETRY, "Curve Modifier");
+ struct Depsgraph *depsgraph = DEG_get_graph_from_handle(ctx->node);
+ DEG_add_object_relation(ctx->node, cmd->object, DEG_OB_COMP_GEOMETRY, "Curve Modifier");
DEG_add_special_eval_flag(depsgraph, &cmd->object->id, DAG_EVAL_NEED_CURVE_PATH);
}
- DEG_add_object_relation(node, object, DEG_OB_COMP_TRANSFORM, "Curve Modifier");
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Curve Modifier");
}
static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c
index e7069937868..a804a35954c 100644
--- a/source/blender/modifiers/intern/MOD_datatransfer.c
+++ b/source/blender/modifiers/intern/MOD_datatransfer.c
@@ -125,15 +125,11 @@ static void foreachObjectLink(
walk(userData, ob, &dtmd->ob_source, IDWALK_CB_NOP);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
if (dtmd->ob_source != NULL) {
- DEG_add_object_relation(node, dtmd->ob_source, DEG_OB_COMP_GEOMETRY, "DataTransfer Modifier");
+ DEG_add_object_relation(ctx->node, dtmd->ob_source, DEG_OB_COMP_GEOMETRY, "DataTransfer Modifier");
}
}
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index 53a77b6fe38..7ec89b23f25 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -80,14 +80,6 @@ static void copyData(ModifierData *md, ModifierData *target)
modifier_copyData_generic(md, target);
}
-static void freeData(ModifierData *md)
-{
- DisplaceModifierData *dmd = (DisplaceModifierData *) md;
- if (dmd->texture) {
- id_us_min(&dmd->texture->id);
- }
-}
-
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
{
DisplaceModifierData *dmd = (DisplaceModifierData *)md;
@@ -154,21 +146,17 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
return ((!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) || dmd->strength == 0.0f);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *ob,
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
DisplaceModifierData *dmd = (DisplaceModifierData *)md;
if (dmd->map_object != NULL && dmd->texmapping == MOD_DISP_MAP_OBJECT) {
- DEG_add_object_relation(node, dmd->map_object, DEG_OB_COMP_TRANSFORM, "Displace Modifier");
+ DEG_add_object_relation(ctx->node, dmd->map_object, DEG_OB_COMP_TRANSFORM, "Displace Modifier");
}
if (dmd->texmapping == MOD_DISP_MAP_GLOBAL ||
(ELEM(dmd->direction, MOD_DISP_DIR_X, MOD_DISP_DIR_Y, MOD_DISP_DIR_Z, MOD_DISP_DIR_RGB_XYZ) &&
dmd->space == MOD_DISP_SPACE_GLOBAL))
{
- DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "Displace Modifier");
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Displace Modifier");
}
}
@@ -426,7 +414,7 @@ ModifierTypeInfo modifierType_Displace = {
/* applyModifierEM */ NULL,
/* initData */ initData,
/* requiredDataMask */ requiredDataMask,
- /* freeData */ freeData,
+ /* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index cf3f84364ea..914b4101760 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -29,7 +29,7 @@
#include "DNA_dynamicpaint_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_scene_types.h"
#include "BLI_utildefines.h"
@@ -132,22 +132,18 @@ static bool is_brush_cb(Object *UNUSED(ob), ModifierData *pmd)
return ((DynamicPaintModifierData *)pmd)->brush != NULL;
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *scene,
- Object *ob,
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
/* Add relation from canvases to all brush objects. */
if (pmd->canvas != NULL) {
for (DynamicPaintSurface *surface = pmd->canvas->surfaces.first; surface; surface = surface->next) {
if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) {
- DEG_add_forcefield_relations(node, scene, ob, surface->effector_weights, true, 0, "Dynamic Paint Field");
+ DEG_add_forcefield_relations(ctx->node, ctx->scene, ctx->object, surface->effector_weights, true, 0, "Dynamic Paint Field");
}
/* Actual code uses custom loop over group/scene without layer checks in dynamicPaint_doStep */
- DEG_add_collision_relations(node, scene, ob, surface->brush_group, eModifierType_DynamicPaint, is_brush_cb, false, "Dynamic Paint Brush");
+ DEG_add_collision_relations(ctx->node, ctx->scene, ctx->object, surface->brush_group, eModifierType_DynamicPaint, is_brush_cb, false, "Dynamic Paint Brush");
}
}
}
diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c
index f9e7f10653b..403a8706295 100644
--- a/source/blender/modifiers/intern/MOD_fluidsim.c
+++ b/source/blender/modifiers/intern/MOD_fluidsim.c
@@ -34,7 +34,7 @@
#include "DNA_scene_types.h"
-#include "DNA_object_fluidsim.h"
+#include "DNA_object_fluidsim_types.h"
#include "DNA_object_types.h"
#include "BLI_utildefines.h"
@@ -103,28 +103,24 @@ static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationConte
return result ? result : dm;
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *scene,
- Object *ob,
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
FluidsimModifierData *fluidmd = (FluidsimModifierData *) md;
if (fluidmd && fluidmd->fss) {
if (fluidmd->fss->type == OB_FLUIDSIM_DOMAIN) {
- FOREACH_SCENE_OBJECT(scene, ob1)
+ FOREACH_SCENE_OBJECT_BEGIN(ctx->scene, ob1)
{
- if (ob1 != ob) {
+ if (ob1 != ctx->object) {
FluidsimModifierData *fluidmdtmp =
(FluidsimModifierData *)modifiers_findByType(ob1, eModifierType_Fluidsim);
/* Only put dependencies from NON-DOMAIN fluids in here. */
if (fluidmdtmp && fluidmdtmp->fss && (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN)) {
- DEG_add_object_relation(node, ob1, DEG_OB_COMP_TRANSFORM, "Fluidsim Object");
+ DEG_add_object_relation(ctx->node, ob1, DEG_OB_COMP_TRANSFORM, "Fluidsim Object");
}
}
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
}
}
}
diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c
index c9f475ad228..72c44121e0b 100644
--- a/source/blender/modifiers/intern/MOD_fluidsim_util.c
+++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c
@@ -40,7 +40,7 @@
#include "DNA_scene_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_object_fluidsim.h"
+#include "DNA_object_fluidsim_types.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
@@ -48,7 +48,9 @@
#include "BKE_fluidsim.h" /* ensure definitions here match */
#include "BKE_cdderivedmesh.h"
-#include "BKE_global.h" /* G.main->name only */
+#ifdef WITH_MOD_FLUID
+# include "BKE_global.h"
+#endif
#include "MOD_fluidsim_util.h"
#include "MOD_modifiertypes.h"
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index 25617c84dac..00abcc1c65c 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -116,21 +116,17 @@ static void foreachObjectLink(
walk(userData, ob, &hmd->object, IDWALK_CB_NOP);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *ob,
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
HookModifierData *hmd = (HookModifierData *)md;
if (hmd->object != NULL) {
if (hmd->subtarget[0]) {
- DEG_add_bone_relation(node, hmd->object, hmd->subtarget, DEG_OB_COMP_BONE, "Hook Modifier");
+ DEG_add_bone_relation(ctx->node, hmd->object, hmd->subtarget, DEG_OB_COMP_BONE, "Hook Modifier");
}
- DEG_add_object_relation(node, hmd->object, DEG_OB_COMP_TRANSFORM, "Hook Modifier");
+ DEG_add_object_relation(ctx->node, hmd->object, DEG_OB_COMP_TRANSFORM, "Hook Modifier");
}
/* We need own transformation as well. */
- DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "Hook Modifier");
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Hook Modifier");
}
struct HookData_cb {
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
index cd8b6139d75..4bf52f552ce 100644
--- a/source/blender/modifiers/intern/MOD_lattice.c
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -89,18 +89,14 @@ static void foreachObjectLink(
walk(userData, ob, &lmd->object, IDWALK_CB_NOP);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *object,
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
LatticeModifierData *lmd = (LatticeModifierData *)md;
if (lmd->object != NULL) {
- DEG_add_object_relation(node, lmd->object, DEG_OB_COMP_GEOMETRY, "Lattice Modifier");
- DEG_add_object_relation(node, lmd->object, DEG_OB_COMP_TRANSFORM, "Lattice Modifier");
+ DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_GEOMETRY, "Lattice Modifier");
+ DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_TRANSFORM, "Lattice Modifier");
}
- DEG_add_object_relation(node, object, DEG_OB_COMP_TRANSFORM, "Lattice Modifier");
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Lattice Modifier");
}
static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c
index bcebbc40adb..080dc371508 100644
--- a/source/blender/modifiers/intern/MOD_mask.c
+++ b/source/blender/modifiers/intern/MOD_mask.c
@@ -78,18 +78,14 @@ static void foreachObjectLink(
walk(userData, ob, &mmd->ob_arm, IDWALK_CB_NOP);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
MaskModifierData *mmd = (MaskModifierData *)md;
if (mmd->ob_arm) {
bArmature *arm = (bArmature *)mmd->ob_arm->data;
/* Tag relationship in depsgraph, but also on the armature. */
/* TODO(sergey): Is it a proper relation here? */
- DEG_add_object_relation(node, mmd->ob_arm, DEG_OB_COMP_TRANSFORM, "Mask Modifier");
+ DEG_add_object_relation(ctx->node, mmd->ob_arm, DEG_OB_COMP_TRANSFORM, "Mask Modifier");
arm->flag |= ARM_HAS_VIZ_DEPS;
}
}
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index da233a18d0a..d7f4af8df63 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -49,6 +49,8 @@
#include "MEM_guardedalloc.h"
+#include "DEG_depsgraph.h"
+
#include "MOD_util.h"
#ifdef __SSE2__
@@ -120,16 +122,12 @@ static void foreachObjectLink(
walk(userData, ob, &mmd->object, IDWALK_CB_NOP);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
MeshDeformModifierData *mmd = (MeshDeformModifierData *)md;
if (mmd->object != NULL) {
/* TODO(sergey): Do we need transform component here? */
- DEG_add_object_relation(node, mmd->object, DEG_OB_COMP_GEOMETRY, "Mesh Deform Modifier");
+ DEG_add_object_relation(ctx->node, mmd->object, DEG_OB_COMP_GEOMETRY, "Mesh Deform Modifier");
}
}
@@ -300,7 +298,7 @@ static void meshdeformModifier_do(
*
* We'll support this case once granular dependency graph is landed.
*/
- if (mmd->object == md->scene->obedit) {
+ if (mmd->object->mode & OB_MODE_EDIT) {
BMEditMesh *em = BKE_editmesh_from_object(mmd->object);
tmpdm = editbmesh_get_derived_cage_and_final(eval_ctx, md->scene, mmd->object, em, 0, &cagedm);
if (tmpdm)
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c
index e28459814e2..10e1cdea4ca 100644
--- a/source/blender/modifiers/intern/MOD_meshsequencecache.c
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c
@@ -33,7 +33,6 @@
#include "BKE_cachefile.h"
#include "BKE_DerivedMesh.h"
#include "BKE_cdderivedmesh.h"
-#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_scene.h"
@@ -44,6 +43,7 @@
#ifdef WITH_ALEMBIC
# include "ABC_alembic.h"
+# include "BKE_global.h"
#endif
static void initData(ModifierData *md)
@@ -74,10 +74,6 @@ static void freeData(ModifierData *md)
{
MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md;
- if (mcmd->cache_file) {
- id_us_min(&mcmd->cache_file->id);
- }
-
if (mcmd->reader) {
#ifdef WITH_ALEMBIC
CacheReader_free(mcmd->reader);
@@ -173,19 +169,13 @@ static void foreachIDLink(ModifierData *md, Object *ob,
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *bmain,
- struct Scene *scene,
- Object *ob,
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md;
if (mcmd->cache_file != NULL) {
- DEG_add_object_cache_relation(node, mcmd->cache_file, DEG_OB_COMP_CACHE, "Mesh Cache File");
+ DEG_add_object_cache_relation(ctx->node, mcmd->cache_file, DEG_OB_COMP_CACHE, "Mesh Cache File");
}
-
- UNUSED_VARS(bmain, scene, ob);
}
ModifierTypeInfo modifierType_MeshSequenceCache = {
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 1b725e335a4..62de2711b3d 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -76,17 +76,13 @@ static void foreachObjectLink(
walk(userData, ob, &mmd->mirror_ob, IDWALK_CB_NOP);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *ob,
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
MirrorModifierData *mmd = (MirrorModifierData *)md;
if (mmd->mirror_ob != NULL) {
- DEG_add_object_relation(node, mmd->mirror_ob, DEG_OB_COMP_TRANSFORM, "Mirror Modifier");
+ DEG_add_object_relation(ctx->node, mmd->mirror_ob, DEG_OB_COMP_TRANSFORM, "Mirror Modifier");
}
- DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "Mirror Modifier");
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Mirror Modifier");
}
static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c
index 61a5b9bb03e..4fc49234468 100644
--- a/source/blender/modifiers/intern/MOD_normal_edit.c
+++ b/source/blender/modifiers/intern/MOD_normal_edit.c
@@ -509,15 +509,11 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
return !is_valid_target(enmd);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
NormalEditModifierData *enmd = (NormalEditModifierData *) md;
if (enmd->target) {
- DEG_add_object_relation(node, enmd->target, DEG_OB_COMP_TRANSFORM, "NormalEdit Modifier");
+ DEG_add_object_relation(ctx->node, enmd->target, DEG_OB_COMP_TRANSFORM, "NormalEdit Modifier");
}
}
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index 09966da13a2..7979751395a 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -44,7 +44,6 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_effect.h"
-#include "BKE_global.h"
#include "BKE_lattice.h"
#include "BKE_library_query.h"
#include "BKE_modifier.h"
@@ -111,15 +110,11 @@ static bool isDisabled(ModifierData *md, int useRenderParams)
return false;
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
if (pimd->ob != NULL) {
- DEG_add_object_relation(node, pimd->ob, DEG_OB_COMP_TRANSFORM, "Particle Instance Modifier");
+ DEG_add_object_relation(ctx->node, pimd->ob, DEG_OB_COMP_TRANSFORM, "Particle Instance Modifier");
}
}
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 979dc339e4e..5f30b762275 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -1117,15 +1117,11 @@ static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationConte
return result;
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
ScrewModifierData *ltmd = (ScrewModifierData *)md;
if (ltmd->ob_axis != NULL) {
- DEG_add_object_relation(node, ltmd->ob_axis, DEG_OB_COMP_TRANSFORM, "Screw Modifier");
+ DEG_add_object_relation(ctx->node, ltmd->ob_axis, DEG_OB_COMP_TRANSFORM, "Screw Modifier");
}
}
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index c87fdd321ab..cbb96b31db1 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -142,20 +142,16 @@ static void deformVertsEM(ModifierData *md, const struct EvaluationContext *UNUS
dm->release(dm);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
if (smd->target != NULL) {
- DEG_add_object_relation(node, smd->target, DEG_OB_COMP_TRANSFORM, "Shrinkwrap Modifier");
- DEG_add_object_relation(node, smd->target, DEG_OB_COMP_GEOMETRY, "Shrinkwrap Modifier");
+ DEG_add_object_relation(ctx->node, smd->target, DEG_OB_COMP_TRANSFORM, "Shrinkwrap Modifier");
+ DEG_add_object_relation(ctx->node, smd->target, DEG_OB_COMP_GEOMETRY, "Shrinkwrap Modifier");
}
if (smd->auxTarget != NULL) {
- DEG_add_object_relation(node, smd->auxTarget, DEG_OB_COMP_TRANSFORM, "Shrinkwrap Modifier");
- DEG_add_object_relation(node, smd->auxTarget, DEG_OB_COMP_GEOMETRY, "Shrinkwrap Modifier");
+ DEG_add_object_relation(ctx->node, smd->auxTarget, DEG_OB_COMP_TRANSFORM, "Shrinkwrap Modifier");
+ DEG_add_object_relation(ctx->node, smd->auxTarget, DEG_OB_COMP_GEOMETRY, "Shrinkwrap Modifier");
}
}
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index 6116e49d07d..8590deb508a 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -375,15 +375,11 @@ static void foreachObjectLink(
walk(userData, ob, &smd->origin, IDWALK_CB_NOP);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md;
if (smd->origin != NULL) {
- DEG_add_object_relation(node, smd->origin, DEG_OB_COMP_TRANSFORM, "SimpleDeform Modifier");
+ DEG_add_object_relation(ctx->node, smd->origin, DEG_OB_COMP_TRANSFORM, "SimpleDeform Modifier");
}
}
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index 97afe6d5e87..4afe6ca33e2 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -1304,9 +1304,9 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f
else if (split_face->len > 4) {
/* Maintain a dynamic vert array containing the split_face's
* vertices, avoids frequent allocs in collapse_face_corners() */
- if (BLI_array_count(vert_buf) < split_face->len) {
+ if (BLI_array_len(vert_buf) < split_face->len) {
BLI_array_grow_items(vert_buf, (split_face->len -
- BLI_array_count(vert_buf)));
+ BLI_array_len(vert_buf)));
}
/* Get split face's verts */
@@ -1470,7 +1470,7 @@ static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd)
while (!BLI_heap_is_empty(heap)) {
BMFace *adj[2];
- e = BLI_heap_popmin(heap);
+ e = BLI_heap_pop_min(heap);
if (BM_edge_face_pair(e, &adj[0], &adj[1])) {
/* If both triangles still free, and if they don't already
diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c
index e66afe07841..e610ef5f78d 100644
--- a/source/blender/modifiers/intern/MOD_smoke.c
+++ b/source/blender/modifiers/intern/MOD_smoke.c
@@ -41,7 +41,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_smoke_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "BLI_utildefines.h"
@@ -131,20 +131,16 @@ static bool is_coll_cb(Object *UNUSED(ob), ModifierData *md)
return (smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll;
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *scene,
- Object *ob,
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
SmokeModifierData *smd = (SmokeModifierData *)md;
if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
/* Actual code uses get_collisionobjects */
- DEG_add_collision_relations(node, scene, ob, smd->domain->fluid_group, eModifierType_Smoke, is_flow_cb, true, "Smoke Flow");
- DEG_add_collision_relations(node, scene, ob, smd->domain->coll_group, eModifierType_Smoke, is_coll_cb, true, "Smoke Coll");
+ DEG_add_collision_relations(ctx->node, ctx->scene, ctx->object, smd->domain->fluid_group, eModifierType_Smoke, is_flow_cb, true, "Smoke Flow");
+ DEG_add_collision_relations(ctx->node, ctx->scene, ctx->object, smd->domain->coll_group, eModifierType_Smoke, is_coll_cb, true, "Smoke Coll");
- DEG_add_forcefield_relations(node, scene, ob, smd->domain->effector_weights, true, PFIELD_SMOKEFLOW, "Smoke Force Field");
+ DEG_add_forcefield_relations(ctx->node, ctx->scene, ctx->object, smd->domain->effector_weights, true, PFIELD_SMOKEFLOW, "Smoke Force Field");
}
}
diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c
index 020dd3da6a5..8d5217391af 100644
--- a/source/blender/modifiers/intern/MOD_softbody.c
+++ b/source/blender/modifiers/intern/MOD_softbody.c
@@ -35,7 +35,7 @@
#include <stdio.h>
#include "DNA_scene_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "BLI_utildefines.h"
@@ -63,17 +63,13 @@ static bool dependsOnTime(ModifierData *UNUSED(md))
return true;
}
-static void updateDepsgraph(ModifierData *UNUSED(md),
- struct Main *UNUSED(bmain),
- struct Scene *scene,
- Object *ob,
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *UNUSED(md), const ModifierUpdateDepsgraphContext *ctx)
{
- if (ob->soft) {
+ if (ctx->object->soft) {
/* Actual code uses ccd_build_deflector_hash */
- DEG_add_collision_relations(node, scene, ob, ob->soft->collision_group, eModifierType_Collision, NULL, false, "Softbody Collision");
+ DEG_add_collision_relations(ctx->node, ctx->scene, ctx->object, ctx->object->soft->collision_group, eModifierType_Collision, NULL, false, "Softbody Collision");
- DEG_add_forcefield_relations(node, scene, ob, ob->soft->effector_weights, true, 0, "Softbody Field");
+ DEG_add_forcefield_relations(ctx->node, ctx->scene, ctx->object, ctx->object->soft->effector_weights, true, 0, "Softbody Field");
}
}
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index 046a0ab27bf..30b569207db 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -11,6 +11,8 @@
#include "BKE_library_query.h"
#include "BKE_modifier.h"
+#include "DEG_depsgraph.h"
+
#include "MEM_guardedalloc.h"
#include "MOD_util.h"
@@ -168,15 +170,11 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
walk(userData, ob, &smd->target, IDWALK_NOP);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
if (smd->target != NULL) {
- DEG_add_object_relation(node, smd->target, DEG_OB_COMP_GEOMETRY, "Surface Deform Modifier");
+ DEG_add_object_relation(ctx->node, smd->target, DEG_OB_COMP_GEOMETRY, "Surface Deform Modifier");
}
}
@@ -1097,7 +1095,9 @@ static void deformVert(
}
}
-static void surfacedeformModifier_do(ModifierData *md, float (*vertexCos)[3], unsigned int numverts, Object *ob)
+static void surfacedeformModifier_do(
+ ModifierData *md,
+ float (*vertexCos)[3], unsigned int numverts, Object *ob)
{
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
DerivedMesh *tdm;
@@ -1110,7 +1110,7 @@ static void surfacedeformModifier_do(ModifierData *md, float (*vertexCos)[3], un
}
/* Handle target mesh both in and out of edit mode */
- if (smd->target == md->scene->obedit) {
+ if (smd->target->mode & OB_MODE_EDIT) {
BMEditMesh *em = BKE_editmesh_from_object(smd->target);
tdm = em->derivedFinal;
}
@@ -1180,18 +1180,20 @@ static void surfacedeformModifier_do(ModifierData *md, float (*vertexCos)[3], un
}
}
-static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
- Object *ob, DerivedMesh *UNUSED(derivedData),
- float (*vertexCos)[3], int numVerts,
- ModifierApplyFlag UNUSED(flag))
+static void deformVerts(
+ ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *UNUSED(derivedData),
+ float (*vertexCos)[3], int numVerts,
+ ModifierApplyFlag UNUSED(flag))
{
surfacedeformModifier_do(md, vertexCos, numVerts, ob);
}
-static void deformVertsEM(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
- Object *ob, struct BMEditMesh *UNUSED(editData),
- DerivedMesh *UNUSED(derivedData),
- float (*vertexCos)[3], int numVerts)
+static void deformVertsEM(
+ ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, struct BMEditMesh *UNUSED(editData),
+ DerivedMesh *UNUSED(derivedData),
+ float (*vertexCos)[3], int numVerts)
{
surfacedeformModifier_do(md, vertexCos, numVerts, ob);
}
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 498dd2486f4..02f799fecb9 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -109,17 +109,13 @@ static void foreachIDLink(ModifierData *md, Object *ob,
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
UVProjectModifierData *umd = (UVProjectModifierData *)md;
int i;
for (i = 0; i < umd->num_projectors; ++i) {
if (umd->projectors[i] != NULL) {
- DEG_add_object_relation(node, umd->projectors[i], DEG_OB_COMP_TRANSFORM, "UV Project Modifier");
+ DEG_add_object_relation(ctx->node, umd->projectors[i], DEG_OB_COMP_TRANSFORM, "UV Project Modifier");
}
}
}
diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c
index 32974d68d9d..8af9fd6cde4 100644
--- a/source/blender/modifiers/intern/MOD_uvwarp.c
+++ b/source/blender/modifiers/intern/MOD_uvwarp.c
@@ -232,9 +232,9 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
walk(userData, ob, &umd->object_src, IDWALK_CB_NOP);
}
-static void uv_warp_deps_object_bone(struct DepsNodeHandle *node,
- Object *object,
- const char *bonename)
+static void uv_warp_deps_object_bone_new(struct DepsNodeHandle *node,
+ Object *object,
+ const char *bonename)
{
if (object != NULL) {
if (bonename[0])
@@ -244,16 +244,12 @@ static void uv_warp_deps_object_bone(struct DepsNodeHandle *node,
}
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
UVWarpModifierData *umd = (UVWarpModifierData *) md;
- uv_warp_deps_object_bone(node, umd->object_src, umd->bone_src);
- uv_warp_deps_object_bone(node, umd->object_dst, umd->bone_dst);
+ uv_warp_deps_object_bone_new(ctx->node, umd->object_src, umd->bone_src);
+ uv_warp_deps_object_bone_new(ctx->node, umd->object_dst, umd->bone_dst);
}
ModifierTypeInfo modifierType_UVWarp = {
diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c
index be0be2671b9..204e344b8e1 100644
--- a/source/blender/modifiers/intern/MOD_warp.c
+++ b/source/blender/modifiers/intern/MOD_warp.c
@@ -137,19 +137,15 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "texture");
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
WarpModifierData *wmd = (WarpModifierData *) md;
if (wmd->object_from != NULL && wmd->object_to != NULL) {
- DEG_add_object_relation(node, wmd->object_from, DEG_OB_COMP_TRANSFORM, "Warp Modifier from");
- DEG_add_object_relation(node, wmd->object_to, DEG_OB_COMP_TRANSFORM, "Warp Modifier to");
+ DEG_add_object_relation(ctx->node, wmd->object_from, DEG_OB_COMP_TRANSFORM, "Warp Modifier from");
+ DEG_add_object_relation(ctx->node, wmd->object_to, DEG_OB_COMP_TRANSFORM, "Warp Modifier to");
}
if ((wmd->texmapping == MOD_DISP_MAP_OBJECT) && wmd->map_object != NULL) {
- DEG_add_object_relation(node, wmd->map_object, DEG_OB_COMP_TRANSFORM, "Warp Modifier map");
+ DEG_add_object_relation(ctx->node, wmd->map_object, DEG_OB_COMP_TRANSFORM, "Warp Modifier map");
}
}
diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c
index 1271cccd719..7921ea662a7 100644
--- a/source/blender/modifiers/intern/MOD_wave.c
+++ b/source/blender/modifiers/intern/MOD_wave.c
@@ -78,14 +78,6 @@ static void initData(ModifierData *md)
wmd->defgrp_name[0] = 0;
}
-static void freeData(ModifierData *md)
-{
- WaveModifierData *wmd = (WaveModifierData *) md;
- if (wmd->texture) {
- id_us_min(&wmd->texture->id);
- }
-}
-
static void copyData(ModifierData *md, ModifierData *target)
{
#if 0
@@ -127,18 +119,14 @@ static void foreachTexLink(ModifierData *md, Object *ob,
walk(userData, ob, md, "texture");
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
WaveModifierData *wmd = (WaveModifierData *)md;
if (wmd->objectcenter != NULL) {
- DEG_add_object_relation(node, wmd->objectcenter, DEG_OB_COMP_TRANSFORM, "Wave Modifier");
+ DEG_add_object_relation(ctx->node, wmd->objectcenter, DEG_OB_COMP_TRANSFORM, "Wave Modifier");
}
if (wmd->map_object != NULL) {
- DEG_add_object_relation(node, wmd->map_object, DEG_OB_COMP_TRANSFORM, "Wave Modifier");
+ DEG_add_object_relation(ctx->node, wmd->map_object, DEG_OB_COMP_TRANSFORM, "Wave Modifier");
}
}
@@ -370,7 +358,7 @@ ModifierTypeInfo modifierType_Wave = {
/* applyModifierEM */ NULL,
/* initData */ initData,
/* requiredDataMask */ requiredDataMask,
- /* freeData */ freeData,
+ /* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index 9aa4bad1707..6fdfe215c37 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -78,10 +78,6 @@ static void freeData(ModifierData *md)
{
WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md;
curvemapping_free(wmd->cmap_curve);
-
- if (wmd->mask_texture) {
- id_us_min(&wmd->mask_texture->id);
- }
}
static void copyData(ModifierData *md, ModifierData *target)
@@ -140,18 +136,14 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "mask_texture");
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *ob,
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md;
if (wmd->mask_tex_map_obj != NULL && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
- DEG_add_object_relation(node, wmd->mask_tex_map_obj, DEG_OB_COMP_TRANSFORM, "WeightVGEdit Modifier");
+ DEG_add_object_relation(ctx->node, wmd->mask_tex_map_obj, DEG_OB_COMP_TRANSFORM, "WeightVGEdit Modifier");
}
if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) {
- DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "WeightVGEdit Modifier");
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "WeightVGEdit Modifier");
}
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index ab1264cc9a0..45c41498792 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -125,14 +125,6 @@ static void initData(ModifierData *md)
wmd->mask_tex_mapping = MOD_DISP_MAP_LOCAL;
}
-static void freeData(ModifierData *md)
-{
- WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md;
- if (wmd->mask_texture) {
- id_us_min(&wmd->mask_texture->id);
- }
-}
-
static void copyData(ModifierData *md, ModifierData *target)
{
#if 0
@@ -189,20 +181,16 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "mask_texture");
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *ob,
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md;
if (wmd->mask_tex_map_obj != NULL && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
- DEG_add_object_relation(node, wmd->mask_tex_map_obj, DEG_OB_COMP_TRANSFORM, "WeightVGMix Modifier");
- DEG_add_object_relation(node, wmd->mask_tex_map_obj, DEG_OB_COMP_GEOMETRY, "WeightVGMix Modifier");
+ DEG_add_object_relation(ctx->node, wmd->mask_tex_map_obj, DEG_OB_COMP_TRANSFORM, "WeightVGMix Modifier");
+ DEG_add_object_relation(ctx->node, wmd->mask_tex_map_obj, DEG_OB_COMP_GEOMETRY, "WeightVGMix Modifier");
}
if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) {
- DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "WeightVGMix Modifier");
- DEG_add_object_relation(node, ob, DEG_OB_COMP_GEOMETRY, "WeightVGMix Modifier");
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "WeightVGMix Modifier");
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_GEOMETRY, "WeightVGMix Modifier");
}
}
@@ -413,7 +401,7 @@ ModifierTypeInfo modifierType_WeightVGMix = {
/* applyModifierEM */ NULL,
/* initData */ initData,
/* requiredDataMask */ requiredDataMask,
- /* freeData */ freeData,
+ /* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index 8a5d0f833a8..84c5207830e 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -285,14 +285,6 @@ static void initData(ModifierData *md)
wmd->max_dist = 1.0f; /* vert arbitrary distance, but don't use 0 */
}
-static void freeData(ModifierData *md)
-{
- WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md;
- if (wmd->mask_texture) {
- id_us_min(&wmd->mask_texture->id);
- }
-}
-
static void copyData(ModifierData *md, ModifierData *target)
{
#if 0
@@ -350,24 +342,20 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "mask_texture");
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *ob,
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *)md;
if (wmd->proximity_ob_target != NULL) {
- DEG_add_object_relation(node, wmd->proximity_ob_target, DEG_OB_COMP_TRANSFORM, "WeightVGProximity Modifier");
- DEG_add_object_relation(node, wmd->proximity_ob_target, DEG_OB_COMP_GEOMETRY, "WeightVGProximity Modifier");
+ DEG_add_object_relation(ctx->node, wmd->proximity_ob_target, DEG_OB_COMP_TRANSFORM, "WeightVGProximity Modifier");
+ DEG_add_object_relation(ctx->node, wmd->proximity_ob_target, DEG_OB_COMP_GEOMETRY, "WeightVGProximity Modifier");
}
if (wmd->mask_tex_map_obj != NULL && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
- DEG_add_object_relation(node, wmd->mask_tex_map_obj, DEG_OB_COMP_TRANSFORM, "WeightVGProximity Modifier");
- DEG_add_object_relation(node, wmd->mask_tex_map_obj, DEG_OB_COMP_GEOMETRY, "WeightVGProximity Modifier");
+ DEG_add_object_relation(ctx->node, wmd->mask_tex_map_obj, DEG_OB_COMP_TRANSFORM, "WeightVGProximity Modifier");
+ DEG_add_object_relation(ctx->node, wmd->mask_tex_map_obj, DEG_OB_COMP_GEOMETRY, "WeightVGProximity Modifier");
}
if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) {
- DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "WeightVGProximity Modifier");
- DEG_add_object_relation(node, ob, DEG_OB_COMP_GEOMETRY, "WeightVGProximity Modifier");
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "WeightVGProximity Modifier");
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_GEOMETRY, "WeightVGProximity Modifier");
}
}
@@ -596,7 +584,7 @@ ModifierTypeInfo modifierType_WeightVGProximity = {
/* applyModifierEM */ NULL,
/* initData */ initData,
/* requiredDataMask */ requiredDataMask,
- /* freeData */ freeData,
+ /* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index c83daa185a8..ee70fcf510f 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -32,6 +32,7 @@ set(INC
../blenkernel
../blenlib
../blentranslation
+ ../depsgraph
../gpu
../imbuf
../makesdna
@@ -195,6 +196,7 @@ set(SRC
shader/nodes/node_shader_tangent.c
shader/nodes/node_shader_bevel.c
shader/nodes/node_shader_displacement.c
+ shader/nodes/node_shader_vector_displacement.c
shader/nodes/node_shader_tex_brick.c
shader/nodes/node_shader_tex_checker.c
shader/nodes/node_shader_tex_coord.c
@@ -210,6 +212,7 @@ set(SRC
shader/nodes/node_shader_tex_wave.c
shader/nodes/node_shader_volume_scatter.c
shader/nodes/node_shader_volume_absorption.c
+ shader/nodes/node_shader_volume_principled.c
shader/nodes/node_shader_uvAlongStroke.c
shader/nodes/node_shader_uvmap.c
shader/node_shader_tree.c
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index cbdfd8d3dbf..a507fdbd787 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -80,6 +80,7 @@ void register_node_type_sh_tex_pointdensity(void);
void register_node_type_sh_attribute(void);
void register_node_type_sh_bevel(void);
void register_node_type_sh_displacement(void);
+void register_node_type_sh_vector_displacement(void);
void register_node_type_sh_geometry(void);
void register_node_type_sh_light_path(void);
void register_node_type_sh_light_falloff(void);
@@ -113,6 +114,7 @@ void register_node_type_sh_emission(void);
void register_node_type_sh_holdout(void);
void register_node_type_sh_volume_absorption(void);
void register_node_type_sh_volume_scatter(void);
+void register_node_type_sh_volume_principled(void);
void register_node_type_sh_bsdf_hair(void);
void register_node_type_sh_subsurface_scattering(void);
void register_node_type_sh_mix_shader(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index e2c1fae1bde..44713a7a000 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -93,6 +93,7 @@ DefNode( ShaderNode, SH_NODE_BSDF_HAIR, def_hair, "BS
DefNode( ShaderNode, SH_NODE_SUBSURFACE_SCATTERING, def_sh_subsurface, "SUBSURFACE_SCATTERING",SubsurfaceScattering,"Subsurface Scattering","")
DefNode( ShaderNode, SH_NODE_VOLUME_ABSORPTION, 0, "VOLUME_ABSORPTION", VolumeAbsorption, "Volume Absorption", "" )
DefNode( ShaderNode, SH_NODE_VOLUME_SCATTER, 0, "VOLUME_SCATTER", VolumeScatter, "Volume Scatter", "" )
+DefNode( ShaderNode, SH_NODE_VOLUME_PRINCIPLED, 0, "PRINCIPLED_VOLUME", VolumePrincipled, "Principled Volume", "" )
DefNode( ShaderNode, SH_NODE_EMISSION, 0, "EMISSION", Emission, "Emission", "" )
DefNode( ShaderNode, SH_NODE_NEW_GEOMETRY, 0, "NEW_GEOMETRY", NewGeometry, "Geometry", "" )
DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LIGHT_PATH", LightPath, "Light Path", "" )
@@ -128,7 +129,8 @@ DefNode( ShaderNode, SH_NODE_UVALONGSTROKE, def_sh_uvalongstroke, "UV
DefNode( ShaderNode, SH_NODE_SEPXYZ, 0, "SEPXYZ", SeparateXYZ, "Separate XYZ", "" )
DefNode( ShaderNode, SH_NODE_COMBXYZ, 0, "COMBXYZ", CombineXYZ, "Combine XYZ", "" )
DefNode( ShaderNode, SH_NODE_BEVEL, def_sh_bevel, "BEVEL", Bevel, "Bevel", "" )
-DefNode( ShaderNode, SH_NODE_DISPLACEMENT, 0, "DISPLACEMENT", Displacement, "Displacement", "" )
+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( 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/intern/node_util.c b/source/blender/nodes/intern/node_util.c
index 43d4136d556..9f04c12fb5e 100644
--- a/source/blender/nodes/intern/node_util.c
+++ b/source/blender/nodes/intern/node_util.c
@@ -124,6 +124,11 @@ void node_filter_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int m
/* test if two sockets are interchangeable */
static bool node_link_socket_match(bNodeSocket *a, bNodeSocket *b)
{
+ /* check if sockets are of the same type */
+ if (a->typeinfo != b->typeinfo) {
+ return false;
+ }
+
/* tests if alphabetic prefix matches
* this allows for imperfect matches, such as numeric suffixes,
* like Color1/Color2
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 2f65188841e..fd30df4293e 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -736,10 +736,10 @@ bool ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
/* ensure execdata is only initialized once */
if (!exec) {
- BLI_lock_thread(LOCK_NODES);
+ BLI_thread_lock(LOCK_NODES);
if (!ntree->execdata)
ntree->execdata = ntreeShaderBeginExecTree(ntree);
- BLI_unlock_thread(LOCK_NODES);
+ BLI_thread_unlock(LOCK_NODES);
exec = ntree->execdata;
}
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index 8559765e315..22171f28790 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -147,7 +147,6 @@ void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns)
zero_v4(gs->vec);
gs->link = NULL;
gs->type = GPU_NONE;
- gs->name = "";
gs->hasinput = false;
gs->hasoutput = false;
gs->sockettype = type;
@@ -167,7 +166,6 @@ void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns)
else
gs->type = GPU_NONE;
- gs->name = "";
gs->hasinput = ns->hasinput && ns->data;
/* XXX Commented out the ns->data check here, as it seems it's not always set,
* even though there *is* a valid connection/output... But that might need
@@ -193,7 +191,7 @@ static void gpu_stack_from_data_list(GPUNodeStack *gs, ListBase *sockets, bNodeS
for (sock = sockets->first, i = 0; sock; sock = sock->next, i++)
node_gpu_stack_from_data(&gs[i], sock->type, ns[i]);
- gs[i].type = GPU_NONE;
+ gs[i].end = true;
}
static void data_from_gpu_stack_list(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs)
diff --git a/source/blender/nodes/shader/nodes/node_shader_attribute.c b/source/blender/nodes/shader/nodes/node_shader_attribute.c
index 5f3699e52eb..0ea1348df05 100644
--- a/source/blender/nodes/shader/nodes/node_shader_attribute.c
+++ b/source/blender/nodes/shader/nodes/node_shader_attribute.c
@@ -59,6 +59,11 @@ static int node_shader_gpu_attribute(GPUMaterial *mat, bNode *node, bNodeExecDat
return GPU_stack_link(mat, node, "node_attribute_volume_flame", in, out,
GPU_builtin(GPU_VOLUME_FLAME));
}
+ else if (strcmp(attr->name, "temperature") == 0) {
+ return GPU_stack_link(mat, node, "node_attribute_volume_temperature", in, out,
+ GPU_builtin(GPU_VOLUME_FLAME),
+ GPU_builtin(GPU_VOLUME_TEMPERATURE));
+ }
else {
GPUNodeLink *cd_attr = GPU_attribute(CD_AUTO_FROM_NAME, attr->name);
return GPU_stack_link(mat, node, "node_attribute", in, out, cd_attr);
diff --git a/source/blender/nodes/shader/nodes/node_shader_blackbody.c b/source/blender/nodes/shader/nodes/node_shader_blackbody.c
index af89a959554..28019651926 100644
--- a/source/blender/nodes/shader/nodes/node_shader_blackbody.c
+++ b/source/blender/nodes/shader/nodes/node_shader_blackbody.c
@@ -38,6 +38,16 @@ static bNodeSocketTemplate sh_node_blackbody_out[] = {
{ -1, 0, "" }
};
+static int node_shader_gpu_blackbody(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ const int size = 256;
+ float *data = MEM_mallocN(sizeof(float) * size * 4, "blackbody texture");
+
+ blackbody_temperature_to_rgb_table(data, size, 965.0f, 12000.0f);
+
+ return GPU_stack_link(mat, node, "node_blackbody", in, out, GPU_texture(size, data));
+}
+
/* node type definition */
void register_node_type_sh_blackbody(void)
{
@@ -49,6 +59,7 @@ void register_node_type_sh_blackbody(void)
node_type_socket_templates(&ntype, sh_node_blackbody_in, sh_node_blackbody_out);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
+ node_type_gpu(&ntype, node_shader_gpu_blackbody);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
index 13e8ac67f63..ee3db99d2ab 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
@@ -31,7 +31,7 @@
static bNodeSocketTemplate sh_node_bsdf_anisotropic_in[] = {
{ SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 1, N_("Roughness"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Roughness"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_FLOAT, 1, N_("Anisotropy"), 0.5f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Rotation"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
index 35121b2afed..ad9e7730ad1 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
@@ -31,7 +31,7 @@
static bNodeSocketTemplate sh_node_bsdf_glossy_in[] = {
{ SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 1, N_("Roughness"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Roughness"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" }
};
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
index b0ca4128d19..b4a83c847be 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
@@ -32,8 +32,8 @@
static bNodeSocketTemplate sh_node_bsdf_principled_in[] = {
{ SOCK_RGBA, 1, N_("Base Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Subsurface"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
- { SOCK_VECTOR, 1, N_("Subsurface Radius"), 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f},
- { SOCK_RGBA, 1, N_("Subsurface Color"), 0.7f, 0.1f, 0.1f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 1, N_("Subsurface Radius"), 1.0f, 0.2f, 0.1f, 0.0f, 0.0f, 100.0f},
+ { SOCK_RGBA, 1, N_("Subsurface Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Metallic"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_FLOAT, 1, N_("Specular"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_FLOAT, 1, N_("Specular Tint"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
@@ -60,7 +60,8 @@ static bNodeSocketTemplate sh_node_bsdf_principled_out[] = {
static void node_shader_init_principled(bNodeTree *UNUSED(ntree), bNode *node)
{
- node->custom1 = SHD_GLOSSY_MULTI_GGX;
+ node->custom1 = SHD_GLOSSY_GGX;
+ node->custom2 = SHD_SUBSURFACE_BURLEY;
}
static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
@@ -144,7 +145,7 @@ void register_node_type_sh_bsdf_principled(void)
sh_node_type_base(&ntype, SH_NODE_BSDF_PRINCIPLED, "Principled BSDF", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_principled_in, sh_node_bsdf_principled_out);
- node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
+ node_type_size_preset(&ntype, NODE_SIZE_LARGE);
node_type_init(&ntype, node_shader_init_principled);
node_type_storage(&ntype, "", NULL, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_principled);
diff --git a/source/blender/nodes/shader/nodes/node_shader_displacement.c b/source/blender/nodes/shader/nodes/node_shader_displacement.c
index d5c191b3966..c26968e8d14 100644
--- a/source/blender/nodes/shader/nodes/node_shader_displacement.c
+++ b/source/blender/nodes/shader/nodes/node_shader_displacement.c
@@ -31,6 +31,7 @@
static bNodeSocketTemplate sh_node_displacement_in[] = {
{ SOCK_FLOAT, 0, N_("Height"), 0.00f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
+ { SOCK_FLOAT, 0, N_("Midlevel"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
{ SOCK_FLOAT, 0, N_("Scale"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" }
@@ -41,13 +42,30 @@ static bNodeSocketTemplate sh_node_displacement_out[] = {
{ -1, 0, "" }
};
+static void node_shader_init_displacement(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ node->custom1 = SHD_SPACE_OBJECT; /* space */
+
+ /* Set default value here for backwards compatibility. */
+ for (bNodeSocket *sock = node->inputs.first; sock; sock = sock->next) {
+ if (STREQ(sock->name, "Midlevel")) {
+ ((bNodeSocketValueFloat *)sock->default_value)->value = 0.5f;
+ }
+ }
+}
+
static int gpu_shader_displacement(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- if (!in[2].link) {
- GPU_link(mat, "direction_transform_m4v3", GPU_builtin(GPU_VIEW_NORMAL), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &in[2].link);
+ if (!in[3].link) {
+ GPU_link(mat, "direction_transform_m4v3", GPU_builtin(GPU_VIEW_NORMAL), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &in[3].link);
}
- return GPU_stack_link(mat, node, "node_displacement", in, out);
+ if (node->custom1 == SHD_SPACE_OBJECT) {
+ return GPU_stack_link(mat, node, "node_displacement_object", in, out, GPU_builtin(GPU_OBJECT_MATRIX));
+ }
+ else {
+ return GPU_stack_link(mat, node, "node_displacement_world", in, out, GPU_builtin(GPU_OBJECT_MATRIX));
+ }
}
/* node type definition */
@@ -59,6 +77,7 @@ void register_node_type_sh_displacement(void)
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_displacement_in, sh_node_displacement_out);
node_type_storage(&ntype, "", NULL, NULL);
+ node_type_init(&ntype, node_shader_init_displacement);
node_type_gpu(&ntype, gpu_shader_displacement);
nodeRegisterType(&ntype);
diff --git a/source/blender/nodes/shader/nodes/node_shader_hair_info.c b/source/blender/nodes/shader/nodes/node_shader_hair_info.c
index 63adba750cf..6a15c59aa5b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_hair_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_hair_info.c
@@ -33,6 +33,7 @@ static bNodeSocketTemplate outputs[] = {
{ SOCK_FLOAT, 0, N_("Thickness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 0, N_("Tangent Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
/*{ SOCK_FLOAT, 0, N_("Fade"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},*/
+ { SOCK_FLOAT, 0, N_("Random") },
{ -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 36d7522e3e6..7584b5eba4d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
@@ -68,7 +68,7 @@ static void node_shader_exec_normal_map(
float *N = shi->nmapnorm;
int uv_index = 0;
switch (nm->space) {
- case SHD_NORMAL_MAP_TANGENT:
+ case SHD_SPACE_TANGENT:
if (nm->uv_map[0]) {
/* find uv map by name */
for (int i = 0; i < shi->totuv; i++) {
@@ -96,8 +96,8 @@ static void node_shader_exec_normal_map(
}
break;
- case SHD_NORMAL_MAP_OBJECT:
- case SHD_NORMAL_MAP_BLENDER_OBJECT:
+ case SHD_SPACE_OBJECT:
+ case SHD_SPACE_BLENDER_OBJECT:
if (shi->use_world_space_shading) {
mul_mat3_m4_v3((float (*)[4])RE_object_instance_get_matrix(shi->obi, RE_OBJECT_INSTANCE_MATRIX_OB), vecIn);
mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEWINV_MATRIX), N);
@@ -107,8 +107,8 @@ static void node_shader_exec_normal_map(
interp_v3_v3v3(out[0]->vec, N, vecIn, strength);
break;
- case SHD_NORMAL_MAP_WORLD:
- case SHD_NORMAL_MAP_BLENDER_WORLD:
+ case SHD_SPACE_WORLD:
+ case SHD_SPACE_BLENDER_WORLD:
if (shi->use_world_space_shading)
mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEWINV_MATRIX), N);
else
@@ -150,10 +150,10 @@ static int gpu_shader_normal_map(GPUMaterial *mat, bNode *node, bNodeExecData *U
/* ******* CYCLES or BLENDER INTERNAL with world space shading flag ******* */
const char *color_to_normal_fnc_name = "color_to_normal_new_shading";
- if (nm->space == SHD_NORMAL_MAP_BLENDER_OBJECT || nm->space == SHD_NORMAL_MAP_BLENDER_WORLD || !GPU_material_use_new_shading_nodes(mat))
+ if (nm->space == SHD_SPACE_BLENDER_OBJECT || nm->space == SHD_SPACE_BLENDER_WORLD || !GPU_material_use_new_shading_nodes(mat))
color_to_normal_fnc_name = "color_to_blender_normal_new_shading";
switch (nm->space) {
- case SHD_NORMAL_MAP_TANGENT:
+ case SHD_SPACE_TANGENT:
GPU_link(mat, "color_to_normal_new_shading", realnorm, &realnorm);
GPU_link(mat, "node_normal_map", GPU_attribute(CD_TANGENT, nm->uv_map), negnorm, realnorm, &realnorm);
GPU_link(mat, "vec_math_mix", strength, realnorm, GPU_builtin(GPU_VIEW_NORMAL), &out[0].link);
@@ -161,14 +161,14 @@ static int gpu_shader_normal_map(GPUMaterial *mat, bNode *node, bNodeExecData *U
GPU_link(mat, "direction_transform_m4v3", out[0].link, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &out[0].link);
GPU_link(mat, "vect_normalize", out[0].link, &out[0].link);
return true;
- case SHD_NORMAL_MAP_OBJECT:
- case SHD_NORMAL_MAP_BLENDER_OBJECT:
+ case SHD_SPACE_OBJECT:
+ case SHD_SPACE_BLENDER_OBJECT:
GPU_link(mat, "direction_transform_m4v3", negnorm, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &negnorm);
GPU_link(mat, color_to_normal_fnc_name, realnorm, &realnorm);
GPU_link(mat, "direction_transform_m4v3", realnorm, GPU_builtin(GPU_OBJECT_MATRIX), &realnorm);
break;
- case SHD_NORMAL_MAP_WORLD:
- case SHD_NORMAL_MAP_BLENDER_WORLD:
+ case SHD_SPACE_WORLD:
+ case SHD_SPACE_BLENDER_WORLD:
GPU_link(mat, "direction_transform_m4v3", negnorm, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &negnorm);
GPU_link(mat, color_to_normal_fnc_name, realnorm, &realnorm);
break;
@@ -184,15 +184,15 @@ static int gpu_shader_normal_map(GPUMaterial *mat, bNode *node, bNodeExecData *U
GPU_link(mat, "vec_math_negate", negnorm, &negnorm);
switch (nm->space) {
- case SHD_NORMAL_MAP_TANGENT:
+ case SHD_SPACE_TANGENT:
GPU_link(mat, "node_normal_map", GPU_attribute(CD_TANGENT, nm->uv_map), negnorm, realnorm, &realnorm);
break;
- case SHD_NORMAL_MAP_OBJECT:
- case SHD_NORMAL_MAP_BLENDER_OBJECT:
+ case SHD_SPACE_OBJECT:
+ case SHD_SPACE_BLENDER_OBJECT:
GPU_link(mat, "direction_transform_m4v3", realnorm, GPU_builtin(GPU_LOC_TO_VIEW_MATRIX), &realnorm);
break;
- case SHD_NORMAL_MAP_WORLD:
- case SHD_NORMAL_MAP_BLENDER_WORLD:
+ case SHD_SPACE_WORLD:
+ case SHD_SPACE_BLENDER_WORLD:
GPU_link(mat, "direction_transform_m4v3", realnorm, GPU_builtin(GPU_VIEW_MATRIX), &realnorm);
break;
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_particle_info.c b/source/blender/nodes/shader/nodes/node_shader_particle_info.c
index 8bdc88292e7..69fcbba8f88 100644
--- a/source/blender/nodes/shader/nodes/node_shader_particle_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_particle_info.c
@@ -30,6 +30,7 @@
static bNodeSocketTemplate outputs[] = {
{ SOCK_FLOAT, 0, "Index" },
+ { SOCK_FLOAT, 0, "Random" },
{ SOCK_FLOAT, 0, "Age" },
{ SOCK_FLOAT, 0, "Lifetime" },
{ SOCK_VECTOR, 0, "Location" },
@@ -45,7 +46,7 @@ static void node_shader_exec_particle_info(void *data, int UNUSED(thread), bNode
{
ShadeInput *shi = ((ShaderCallData *)data)->shi;
- RE_instance_get_particle_info(shi->obi, out[0]->vec, out[1]->vec, out[2]->vec, out[3]->vec, out[4]->vec, out[5]->vec, out[6]->vec);
+ RE_instance_get_particle_info(shi->obi, out[0]->vec, out[1]->vec, out[2]->vec, out[3]->vec, out[4]->vec, out[5]->vec, out[6]->vec, out[7]->vec);
}
static int gpu_shader_particle_info(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
diff --git a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
index 116825ff0da..4b4f08a8b56 100644
--- a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
+++ b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
@@ -32,7 +32,7 @@
static bNodeSocketTemplate sh_node_subsurface_scattering_in[] = {
{ SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Scale"), 1.0, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
- { SOCK_VECTOR, 1, N_("Radius"), 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f},
+ { SOCK_VECTOR, 1, N_("Radius"), 1.0f, 0.2f, 0.1f, 0.0f, 0.0f, 100.0f},
{ SOCK_FLOAT, 1, N_("Sharpness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_FLOAT, 1, N_("Texture Blur"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
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 4d98b142f37..8a65ee89ffc 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
@@ -102,6 +102,7 @@ void register_node_type_sh_tex_environment(void)
node_type_init(&ntype, node_shader_init_tex_environment);
node_type_storage(&ntype, "NodeTexEnvironment", node_free_standard_storage, node_copy_standard_storage);
node_type_gpu(&ntype, node_shader_gpu_tex_environment);
+ node_type_label(&ntype, node_image_label);
nodeRegisterType(&ntype);
}
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 c86a502b666..22f302a9c59 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -126,6 +126,7 @@ void register_node_type_sh_tex_image(void)
node_type_init(&ntype, node_shader_init_tex_image);
node_type_storage(&ntype, "NodeTexImage", node_free_standard_storage, node_copy_standard_storage);
node_type_gpu(&ntype, node_shader_gpu_tex_image);
+ node_type_label(&ntype, node_image_label);
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 3c165cfcb8a..74e23aed7de 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vectTransform.c
+++ b/source/blender/nodes/shader/nodes/node_shader_vectTransform.c
@@ -202,7 +202,7 @@ void register_node_type_sh_vect_transform(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_VECT_TRANSFORM, "Vector Transform", NODE_CLASS_CONVERTOR, 0);
+ sh_node_type_base(&ntype, SH_NODE_VECT_TRANSFORM, "Vector Transform", NODE_CLASS_OP_VECTOR, 0);
node_type_compatibility(&ntype, NODE_OLD_SHADING | NODE_NEW_SHADING);
node_type_init(&ntype, node_shader_init_vect_transform);
node_type_socket_templates(&ntype, sh_node_vect_transform_in, sh_node_vect_transform_out);
diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c b/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c
new file mode 100644
index 00000000000..79b41509fcc
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c
@@ -0,0 +1,83 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** OUTPUT ******************** */
+
+static bNodeSocketTemplate sh_node_vector_displacement_in[] = {
+ { SOCK_RGBA, 0, N_("Vector"), 0.00f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ { SOCK_FLOAT, 0, N_("Midlevel"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
+ { SOCK_FLOAT, 0, N_("Scale"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
+ { -1, 0, "" }
+};
+
+static bNodeSocketTemplate sh_node_vector_displacement_out[] = {
+ { SOCK_VECTOR, 0, N_("Displacement"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static void node_shader_init_vector_displacement(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ node->custom1 = SHD_SPACE_TANGENT; /* space */
+}
+
+static int gpu_shader_vector_displacement(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ if (node->custom1 == SHD_SPACE_TANGENT) {
+ return GPU_stack_link(mat,
+ node,
+ "node_vector_displacement_tangent",
+ in,
+ out,
+ GPU_attribute(CD_TANGENT, ""),
+ GPU_builtin(GPU_VIEW_NORMAL),
+ GPU_builtin(GPU_OBJECT_MATRIX),
+ GPU_builtin(GPU_VIEW_MATRIX));
+ }
+ else if (node->custom1 == SHD_SPACE_OBJECT) {
+ return GPU_stack_link(mat, node, "node_vector_displacement_object", in, out, GPU_builtin(GPU_OBJECT_MATRIX));
+ }
+ else {
+ return GPU_stack_link(mat, node, "node_vector_displacement_world", in, out);
+ }
+}
+
+/* node type definition */
+void register_node_type_sh_vector_displacement(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_VECTOR_DISPLACEMENT, "Vector Displacement", NODE_CLASS_OP_VECTOR, 0);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, sh_node_vector_displacement_in, sh_node_vector_displacement_out);
+ node_type_storage(&ntype, "", NULL, NULL);
+ node_type_init(&ntype, node_shader_init_vector_displacement);
+ node_type_gpu(&ntype, gpu_shader_vector_displacement);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_principled.c b/source/blender/nodes/shader/nodes/node_shader_volume_principled.c
new file mode 100644
index 00000000000..4fbd9af1b58
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_volume_principled.c
@@ -0,0 +1,165 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** OUTPUT ******************** */
+
+static bNodeSocketTemplate sh_node_volume_principled_in[] = {
+ { SOCK_RGBA, 1, N_("Color"), 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f},
+ { SOCK_STRING, 1, N_("Color Attribute"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
+ { SOCK_STRING, 1, N_("Density Attribute"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Anisotropy"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_FACTOR},
+ { SOCK_RGBA, 1, N_("Absorption Color"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Emission Strength"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1000.0f},
+ { SOCK_RGBA, 1, N_("Emission Color"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Blackbody Intensity"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_RGBA, 1, N_("Blackbody Tint"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Temperature"), 1000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 6500.0f},
+ { SOCK_STRING, 1, N_("Temperature Attribute"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeSocketTemplate sh_node_volume_principled_out[] = {
+ { SOCK_SHADER, 0, N_("Volume")},
+ { -1, 0, "" }
+};
+
+static void node_shader_init_volume_principled(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ for (bNodeSocket *sock = node->inputs.first; sock; sock = sock->next) {
+ if (STREQ(sock->name, "Density Attribute")) {
+ strcpy(((bNodeSocketValueString *)sock->default_value)->value, "density");
+ }
+ else if (STREQ(sock->name, "Temperature Attribute")) {
+ strcpy(((bNodeSocketValueString *)sock->default_value)->value, "temperature");
+ }
+ }
+}
+
+static void node_shader_gpu_volume_attribute(GPUMaterial *mat, const char *name, GPUNodeLink **outcol, GPUNodeLink **outvec, GPUNodeLink **outf)
+{
+ if (strcmp(name, "density") == 0) {
+ GPU_link(mat, "node_attribute_volume_density",
+ GPU_builtin(GPU_VOLUME_DENSITY),
+ outcol, outvec, outf);
+ }
+ else if (strcmp(name, "color") == 0) {
+ GPU_link(mat, "node_attribute_volume_color",
+ GPU_builtin(GPU_VOLUME_DENSITY),
+ outcol, outvec, outf);
+ }
+ else if (strcmp(name, "flame") == 0) {
+ GPU_link(mat, "node_attribute_volume_flame",
+ GPU_builtin(GPU_VOLUME_FLAME),
+ outcol, outvec, outf);
+ }
+ else if (strcmp(name, "temperature") == 0) {
+ GPU_link(mat, "node_attribute_volume_temperature",
+ GPU_builtin(GPU_VOLUME_FLAME),
+ GPU_builtin(GPU_VOLUME_TEMPERATURE),
+ outcol, outvec, outf);
+ }
+ else {
+ *outcol = *outvec = *outf = NULL;
+ }
+}
+
+static int node_shader_gpu_volume_principled(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ /* Test if blackbody intensity is enabled. */
+ bool use_blackbody = (in[8].link || in[8].vec[0] != 0.0f);
+
+ /* Get volume attributes. */
+ GPUNodeLink *density = NULL, *color = NULL, *temperature = NULL;
+
+ for (bNodeSocket *sock = node->inputs.first; sock; sock = sock->next) {
+ if (sock->typeinfo->type != SOCK_STRING) {
+ continue;
+ }
+
+ bNodeSocketValueString *value = sock->default_value;
+ GPUNodeLink *outcol, *outvec, *outf;
+
+ if (STREQ(sock->name, "Density Attribute")) {
+ node_shader_gpu_volume_attribute(mat, value->value, &outcol, &outvec, &density);
+ }
+ else if (STREQ(sock->name, "Color Attribute")) {
+ node_shader_gpu_volume_attribute(mat, value->value, &color, &outvec, &outf);
+ }
+ else if (use_blackbody && STREQ(sock->name, "Temperature Attribute")) {
+ node_shader_gpu_volume_attribute(mat, value->value, &outcol, &outvec, &temperature);
+ }
+ }
+
+ /* Default values if attributes not found. */
+ if (!density) {
+ static float one = 1.0f;
+ density = GPU_uniform(&one);
+ }
+ if (!color) {
+ static float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ color = GPU_uniform(white);
+ }
+ if (!temperature) {
+ static float one = 1.0f;
+ temperature = GPU_uniform(&one);
+ }
+
+ /* Create blackbody spectrum. */
+ GPUNodeLink *spectrummap;
+ if (use_blackbody) {
+ const int size = 256;
+ float *data = MEM_mallocN(sizeof(float) * size * 4, "blackbody texture");
+ blackbody_temperature_to_rgb_table(data, size, 965.0f, 12000.0f);
+ spectrummap = GPU_texture(size, data);
+ }
+ else {
+ float *data = MEM_callocN(sizeof(float) * 4, "blackbody black");
+ spectrummap = GPU_texture(1, data);
+ }
+
+ return GPU_stack_link(mat, node, "node_volume_principled", in, out, density, color, temperature, spectrummap);
+}
+
+/* node type definition */
+void register_node_type_sh_volume_principled(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_VOLUME_PRINCIPLED, "Principled Volume", NODE_CLASS_SHADER, 0);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, sh_node_volume_principled_in, sh_node_volume_principled_out);
+ node_type_size_preset(&ntype, NODE_SIZE_LARGE);
+ node_type_init(&ntype, node_shader_init_volume_principled);
+ node_type_storage(&ntype, "", NULL, NULL);
+ node_type_gpu(&ntype, node_shader_gpu_volume_principled);
+
+ nodeRegisterType(&ntype);
+}
+
diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c
index bce4695af10..dfd7154e6b8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c
+++ b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c
@@ -32,7 +32,7 @@
static bNodeSocketTemplate sh_node_volume_scatter_in[] = {
{ SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
- { SOCK_FLOAT, 1, N_("Anisotropy"),0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Anisotropy"),0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_FACTOR},
{ -1, 0, "" }
};
diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c
index dcae9d2345f..932b60665c4 100644
--- a/source/blender/nodes/texture/node_texture_tree.c
+++ b/source/blender/nodes/texture/node_texture_tree.c
@@ -53,12 +53,14 @@
#include "NOD_texture.h"
#include "node_texture_util.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RE_shader_ext.h"
-
-static void texture_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
+static void texture_get_from_context(
+ const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
{
SpaceNode *snode = CTX_wm_space_node(C);
Scene *scene = CTX_data_scene(C);
@@ -346,10 +348,10 @@ int ntreeTexExecTree(
/* ensure execdata is only initialized once */
if (!exec) {
- BLI_lock_thread(LOCK_NODES);
+ BLI_thread_lock(LOCK_NODES);
if (!nodes->execdata)
ntreeTexBeginExecTree(nodes);
- BLI_unlock_thread(LOCK_NODES);
+ BLI_thread_unlock(LOCK_NODES);
exec = nodes->execdata;
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_image.c b/source/blender/nodes/texture/nodes/node_texture_image.c
index 8e9821c0fcb..69c8f4b7262 100644
--- a/source/blender/nodes/texture/nodes/node_texture_image.c
+++ b/source/blender/nodes/texture/nodes/node_texture_image.c
@@ -64,10 +64,10 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(i
if ( (!xsize) || (!ysize) ) return;
if (!ibuf->rect_float) {
- BLI_lock_thread(LOCK_IMAGE);
+ BLI_thread_lock(LOCK_IMAGE);
if (!ibuf->rect_float)
IMB_float_from_rect(ibuf);
- BLI_unlock_thread(LOCK_IMAGE);
+ BLI_thread_unlock(LOCK_IMAGE);
}
while (px < 0) px += ibuf->x;
diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp
index b694b6e994d..5b5639495da 100644
--- a/source/blender/physics/intern/BPH_mass_spring.cpp
+++ b/source/blender/physics/intern/BPH_mass_spring.cpp
@@ -34,7 +34,7 @@ extern "C" {
#include "DNA_cloth_types.h"
#include "DNA_scene_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
diff --git a/source/blender/physics/intern/implicit_blender.c b/source/blender/physics/intern/implicit_blender.c
index 16cd335dc0c..0fdc1d86d5c 100644
--- a/source/blender/physics/intern/implicit_blender.c
+++ b/source/blender/physics/intern/implicit_blender.c
@@ -37,7 +37,7 @@
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_texture_types.h"
@@ -48,7 +48,6 @@
#include "BKE_cloth.h"
#include "BKE_collision.h"
#include "BKE_effect.h"
-#include "BKE_global.h"
#include "BPH_mass_spring.h"
diff --git a/source/blender/physics/intern/implicit_eigen.cpp b/source/blender/physics/intern/implicit_eigen.cpp
index afe1b441632..c36fabcffb0 100644
--- a/source/blender/physics/intern/implicit_eigen.cpp
+++ b/source/blender/physics/intern/implicit_eigen.cpp
@@ -73,7 +73,7 @@
extern "C" {
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_texture_types.h"
diff --git a/source/blender/python/BPY_extern_clog.h b/source/blender/python/BPY_extern_clog.h
new file mode 100644
index 00000000000..fbe7139ba1b
--- /dev/null
+++ b/source/blender/python/BPY_extern_clog.h
@@ -0,0 +1,35 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file BPY_extern_clog.h
+ * \ingroup python
+ *
+ * Logging defines.
+ */
+
+#ifndef __BPY_EXTERN_CLOG_H__
+#define __BPY_EXTERN_CLOG_H__
+
+
+/* bpy_interface.c */
+extern struct CLG_LogRef *BPY_LOG_RNA;
+extern struct CLG_LogRef *BPY_LOG_CONTEXT;
+
+#endif /* __BPY_EXTERN_CLOG_H__ */
diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c
index 6598d402f72..4dce0dc2a22 100644
--- a/source/blender/python/bmesh/bmesh_py_ops_call.c
+++ b/source/blender/python/bmesh/bmesh_py_ops_call.c
@@ -566,7 +566,7 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot)
switch (slot->slot_subtype.map) {
case BMO_OP_SLOT_SUBTYPE_MAP_ELEM:
{
- item = _PyDict_NewPresized(slot_hash ? BLI_ghash_size(slot_hash) : 0);
+ item = _PyDict_NewPresized(slot_hash ? BLI_ghash_len(slot_hash) : 0);
if (slot_hash) {
GHASH_ITER (hash_iter, slot_hash) {
BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter);
@@ -584,7 +584,7 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot)
}
case BMO_OP_SLOT_SUBTYPE_MAP_FLT:
{
- item = _PyDict_NewPresized(slot_hash ? BLI_ghash_size(slot_hash) : 0);
+ item = _PyDict_NewPresized(slot_hash ? BLI_ghash_len(slot_hash) : 0);
if (slot_hash) {
GHASH_ITER (hash_iter, slot_hash) {
BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter);
@@ -602,7 +602,7 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot)
}
case BMO_OP_SLOT_SUBTYPE_MAP_INT:
{
- item = _PyDict_NewPresized(slot_hash ? BLI_ghash_size(slot_hash) : 0);
+ item = _PyDict_NewPresized(slot_hash ? BLI_ghash_len(slot_hash) : 0);
if (slot_hash) {
GHASH_ITER (hash_iter, slot_hash) {
BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter);
@@ -620,7 +620,7 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot)
}
case BMO_OP_SLOT_SUBTYPE_MAP_BOOL:
{
- item = _PyDict_NewPresized(slot_hash ? BLI_ghash_size(slot_hash) : 0);
+ item = _PyDict_NewPresized(slot_hash ? BLI_ghash_len(slot_hash) : 0);
if (slot_hash) {
GHASH_ITER (hash_iter, slot_hash) {
BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter);
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index 629c3a3c7a3..ec787768a57 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -902,7 +902,11 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args)
bm = self->bm;
- BM_mesh_bm_to_me(bm, me, (&(struct BMeshToMeshParams){0}));
+ BM_mesh_bm_to_me(
+ bm, me,
+ (&(struct BMeshToMeshParams){
+ .calc_object_remap = true,
+ }));
/* we could have the user do this but if they forget blender can easy crash
* since the references arrays for the objects derived meshes are now invalid */
diff --git a/source/blender/python/gawain/gwn_py_types.c b/source/blender/python/gawain/gwn_py_types.c
index 4f6b354b7be..9ddad009a12 100644
--- a/source/blender/python/gawain/gwn_py_types.c
+++ b/source/blender/python/gawain/gwn_py_types.c
@@ -117,7 +117,7 @@ static int bpygwn_ParseVertFetchMode(PyObject *o, void *p)
} \
} ((void)0)
- Gwn_VertCompType mode;
+ Gwn_VertFetchMode mode;
MATCH_ID(FLOAT);
MATCH_ID(INT);
MATCH_ID(INT_TO_FLOAT_UNIT);
@@ -168,7 +168,7 @@ static int bpygwn_ParsePrimType(PyObject *o, void *p)
return 0;
success:
- (*(Gwn_VertFetchMode *)p) = mode;
+ (*(Gwn_PrimType *)p) = mode;
return 1;
}
@@ -447,9 +447,9 @@ static PyObject *bpygwn_VertBuf_fill(BPyGwn_VertBuf *self, PyObject *args, PyObj
return NULL;
}
- if (self->buf->vbo_id != 0) {
+ if (self->buf->data == NULL) {
PyErr_SetString(PyExc_ValueError,
- "Can't fill, buffer already in use");
+ "Can't fill, static buffer already in use");
return NULL;
}
diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c
index 827b69f5403..1e2837799e3 100644
--- a/source/blender/python/generic/bgl.c
+++ b/source/blender/python/generic/bgl.c
@@ -1295,11 +1295,20 @@ BGL_Wrap(UniformMatrix4x3fv, void, (GLint, GLsizei, GLboolean, GLflo
/* GL_VERSION_3_0 */
+BGL_Wrap(BindFramebuffer, void, (GLenum, GLuint))
+BGL_Wrap(BindRenderbuffer, void, (GLenum, GLuint))
BGL_Wrap(BindVertexArray, void, (GLuint))
+BGL_Wrap(CheckFramebufferStatus, GLenum, (GLenum))
+BGL_Wrap(DeleteFramebuffers, void, (GLsizei, GLuintP))
+BGL_Wrap(DeleteRenderbuffers, void, (GLsizei, GLuintP))
BGL_Wrap(DeleteVertexArrays, void, (GLsizei, GLuintP))
+BGL_Wrap(FramebufferRenderbuffer, void, (GLenum, GLenum, GLenum, GLuint))
+BGL_Wrap(GenFramebuffers, void, (GLsizei, GLuintP))
+BGL_Wrap(GenRenderbuffers, void, (GLsizei, GLuintP))
BGL_Wrap(GenVertexArrays, void, (GLsizei, GLuintP))
BGL_Wrap(GetStringi, GLstring, (GLenum, GLuint))
BGL_Wrap(IsVertexArray, GLboolean, (GLuint))
+BGL_Wrap(RenderbufferStorage, void, (GLenum, GLenum, GLsizei, GLsizei))
/* GL_VERSION_3_1 */
@@ -1626,11 +1635,20 @@ PyObject *BPyInit_bgl(void)
/* GL_VERSION_3_0 */
{
+ PY_MOD_ADD_METHOD(BindFramebuffer);
+ PY_MOD_ADD_METHOD(BindRenderbuffer);
PY_MOD_ADD_METHOD(BindVertexArray);
+ PY_MOD_ADD_METHOD(CheckFramebufferStatus);
+ PY_MOD_ADD_METHOD(DeleteFramebuffers);
+ PY_MOD_ADD_METHOD(DeleteRenderbuffers);
PY_MOD_ADD_METHOD(DeleteVertexArrays);
+ PY_MOD_ADD_METHOD(FramebufferRenderbuffer);
+ PY_MOD_ADD_METHOD(GenFramebuffers);
+ PY_MOD_ADD_METHOD(GenRenderbuffers);
PY_MOD_ADD_METHOD(GenVertexArrays);
PY_MOD_ADD_METHOD(GetStringi);
PY_MOD_ADD_METHOD(IsVertexArray);
+ PY_MOD_ADD_METHOD(RenderbufferStorage);
}
/* GL_VERSION_3_1 */
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index 36609c6f29b..6f265b2ae87 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -38,6 +38,8 @@
#include "python_utildefines.h"
+#include "BLI_string.h"
+
#ifndef MATH_STANDALONE
/* only for BLI_strncpy_wchar_from_utf8, should replace with py funcs but too late in release now */
#include "BLI_string_utf8.h"
@@ -144,6 +146,15 @@ PyObject *PyC_Tuple_PackArray_F32(const float *array, uint len)
return tuple;
}
+PyObject *PyC_Tuple_PackArray_F64(const double *array, uint len)
+{
+ PyObject *tuple = PyTuple_New(len);
+ for (uint i = 0; i < len; i++) {
+ PyTuple_SET_ITEM(tuple, i, PyFloat_FromDouble(array[i]));
+ }
+ return tuple;
+}
+
PyObject *PyC_Tuple_PackArray_I32(const int *array, uint len)
{
PyObject *tuple = PyTuple_New(len);
@@ -225,22 +236,49 @@ int PyC_ParseBool(PyObject *o, void *p)
/* for debugging */
void PyC_ObSpit(const char *name, PyObject *var)
{
+ const char *null_str = "<null>";
fprintf(stderr, "<%s> : ", name);
if (var == NULL) {
- fprintf(stderr, "<NIL>");
+ fprintf(stderr, "%s\n", null_str);
}
else {
PyObject_Print(var, stderr, 0);
- fprintf(stderr, " ref:%d ", (int)var->ob_refcnt);
- fprintf(stderr, " ptr:%p", (void *)var);
-
- fprintf(stderr, " type:");
- if (Py_TYPE(var))
- fprintf(stderr, "%s", Py_TYPE(var)->tp_name);
- else
- fprintf(stderr, "<NIL>");
+ const PyTypeObject *type = Py_TYPE(var);
+ fprintf(stderr,
+ " ref:%d, ptr:%p, type: %s\n",
+ (int)var->ob_refcnt, (void *)var, type ? type->tp_name : null_str);
+ }
+}
+
+/**
+ * A version of #PyC_ObSpit that writes into a string (and doesn't take a name argument).
+ * Use for logging.
+ */
+void PyC_ObSpitStr(char *result, size_t result_len, PyObject *var)
+{
+ /* No name, creator of string can manage that. */
+ const char *null_str = "<null>";
+ if (var == NULL) {
+ BLI_snprintf(result, result_len, "%s", null_str);
+ }
+ else {
+ const PyTypeObject *type = Py_TYPE(var);
+ PyObject *var_str = PyObject_Repr(var);
+ if (var_str == NULL) {
+ /* We could print error here, but this may be used for generating errors - so don't for now. */
+ PyErr_Clear();
+ }
+ BLI_snprintf(
+ result, result_len,
+ " ref=%d, ptr=%p, type=%s, value=%.200s",
+ (int)var->ob_refcnt,
+ (void *)var,
+ type ? type->tp_name : null_str,
+ var_str ? _PyUnicode_AsString(var_str) : "<error>");
+ if (var_str != NULL) {
+ Py_DECREF(var_str);
+ }
}
- fprintf(stderr, "\n");
}
void PyC_LineSpit(void)
diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h
index 25c88799027..fe7a046d99c 100644
--- a/source/blender/python/generic/py_capi_utils.h
+++ b/source/blender/python/generic/py_capi_utils.h
@@ -31,6 +31,7 @@
#include "BLI_utildefines_variadic.h"
void PyC_ObSpit(const char *name, PyObject *var);
+void PyC_ObSpitStr(char *result, size_t result_len, PyObject *var);
void PyC_LineSpit(void);
void PyC_StackSpit(void);
PyObject * PyC_ExceptionBuffer(void);
@@ -50,12 +51,15 @@ int PyC_AsArray(
const PyTypeObject *type, const bool is_double, const char *error_prefix);
PyObject *PyC_Tuple_PackArray_F32(const float *array, uint len);
+PyObject *PyC_Tuple_PackArray_F64(const double *array, uint len);
PyObject *PyC_Tuple_PackArray_I32(const int *array, uint len);
PyObject *PyC_Tuple_PackArray_I32FromBool(const int *array, uint len);
PyObject *PyC_Tuple_PackArray_Bool(const bool *array, uint len);
#define PyC_Tuple_Pack_F32(...) \
PyC_Tuple_PackArray_F32(((const float []){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
+#define PyC_Tuple_Pack_F64(...) \
+ PyC_Tuple_PackArray_F64(((const double []){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
#define PyC_Tuple_Pack_I32(...) \
PyC_Tuple_PackArray_I32(((const int []){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
#define PyC_Tuple_Pack_I32FromBool(...) \
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index 41018468695..f9098529772 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -23,7 +23,7 @@
#
# ***** END GPL LICENSE BLOCK *****
-set(INC
+set(INC
..
../../blenkernel
../../blenlib
@@ -35,9 +35,10 @@ set(INC
../../makesdna
../../makesrna
../../windowmanager
- ../../../../intern/cycles/blender
- ../../../../intern/opencolorio
+ ../../../../intern/clog
../../../../intern/guardedalloc
+ ../../../../intern/opencolorio
+ ../../../../intern/cycles/blender
)
set(INC_SYS
@@ -119,6 +120,7 @@ set(SRC
bpy_utils_units.h
gpu.h
../BPY_extern.h
+ ../BPY_extern_clog.h
)
# only to check if buildinfo is available
@@ -248,10 +250,6 @@ if(WITH_LIBMV)
add_definitions(-DWITH_LIBMV)
endif()
-if(WITH_MOD_BOOLEAN)
- add_definitions(-DWITH_MOD_BOOLEAN)
-endif()
-
if(WITH_MOD_FLUID)
add_definitions(-DWITH_MOD_FLUID)
endif()
diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index 0b791b6acaa..e07fa46424c 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -376,6 +376,9 @@ void BPy_init_modules(void)
PyModule_AddObject(mod, meth_bpy_register_class.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_register_class, NULL));
PyModule_AddObject(mod, meth_bpy_unregister_class.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_unregister_class, NULL));
+ PyModule_AddObject(mod, meth_bpy_owner_id_get.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_owner_id_get, NULL));
+ PyModule_AddObject(mod, meth_bpy_owner_id_set.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_owner_id_set, NULL));
+
/* add our own modules dir, this is a python package */
bpy_package_py = bpy_import_test("bpy");
}
diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c
index f44401afd7d..1e2ce372727 100644
--- a/source/blender/python/intern/bpy_app.c
+++ b/source/blender/python/intern/bpy_app.c
@@ -357,6 +357,11 @@ static PyGetSetDef bpy_app_getsets[] = {
{(char *)"debug_handlers", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_HANDLERS},
{(char *)"debug_wm", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_WM},
{(char *)"debug_depsgraph", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH},
+ {(char *)"debug_depsgraph_build", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_BUILD},
+ {(char *)"debug_depsgraph_eval", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_EVAL},
+ {(char *)"debug_depsgraph_tag", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_TAG},
+ {(char *)"debug_depsgraph_time", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_TIME},
+ {(char *)"debug_depsgraph_pretty", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_PRETTY},
{(char *)"debug_simdata", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_SIMDATA},
{(char *)"debug_gpumem", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_GPU_MEM},
diff --git a/source/blender/python/intern/bpy_app_build_options.c b/source/blender/python/intern/bpy_app_build_options.c
index 501e09dd6ad..d5c325e4317 100644
--- a/source/blender/python/intern/bpy_app_build_options.c
+++ b/source/blender/python/intern/bpy_app_build_options.c
@@ -58,7 +58,6 @@ static PyStructSequence_Field app_builtopts_info_fields[] = {
{(char *)"sdl_dynload", NULL},
{(char *)"jack", NULL},
{(char *)"libmv", NULL},
- {(char *)"mod_boolean", NULL},
{(char *)"mod_fluid", NULL},
{(char *)"mod_oceansim", NULL},
{(char *)"mod_remesh", NULL},
@@ -237,12 +236,6 @@ static PyObject *make_builtopts_info(void)
SetObjIncref(Py_False);
#endif
-#ifdef WITH_MOD_BOOLEAN
- SetObjIncref(Py_True);
-#else
- SetObjIncref(Py_False);
-#endif
-
#ifdef WITH_MOD_FLUID
SetObjIncref(Py_True);
#else
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 11a233461d8..7156bed0c2b 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -33,6 +33,8 @@
#include "MEM_guardedalloc.h"
+#include "CLG_log.h"
+
#include "BLI_utildefines.h"
#include "BLI_path_util.h"
#include "BLI_fileops.h"
@@ -76,6 +78,9 @@
#include "../bmesh/bmesh_py_api.h"
#include "../mathutils/mathutils.h"
+/* Logging types to use anywhere in the Python modules. */
+CLG_LOGREF_DECLARE_GLOBAL(BPY_LOG_CONTEXT, "bpy.context");
+CLG_LOGREF_DECLARE_GLOBAL(BPY_LOG_RNA, "bpy.rna");
/* for internal use, when starting and ending python scripts */
@@ -803,8 +808,9 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *
CTX_data_list_add(result, ptr->id.data, ptr->type, ptr->data);
}
else {
- printf("PyContext: '%s' list item not a valid type in sequece type '%s'\n",
- member, Py_TYPE(item)->tp_name);
+ CLOG_INFO(BPY_LOG_CONTEXT, 1,
+ "'%s' list item not a valid type in sequence type '%s'",
+ member, Py_TYPE(item)->tp_name);
}
}
@@ -816,16 +822,14 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *
if (done == false) {
if (item) {
- printf("PyContext '%s' not a valid type\n", member);
+ CLOG_INFO(BPY_LOG_CONTEXT, 1, "'%s' not a valid type", member);
}
else {
- printf("PyContext '%s' not found\n", member);
+ CLOG_INFO(BPY_LOG_CONTEXT, 1, "'%s' not found\n", member);
}
}
else {
- if (G.debug & G_DEBUG_PYTHON) {
- printf("PyContext '%s' found\n", member);
- }
+ CLOG_INFO(BPY_LOG_CONTEXT, 2, "'%s' found", member);
}
if (use_gil)
diff --git a/source/blender/python/intern/bpy_msgbus.c b/source/blender/python/intern/bpy_msgbus.c
index 945d2a9b6cc..941d6b760dc 100644
--- a/source/blender/python/intern/bpy_msgbus.c
+++ b/source/blender/python/intern/bpy_msgbus.c
@@ -273,7 +273,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};
@@ -349,7 +349,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.c b/source/blender/python/intern/bpy_operator.c
index 5b84a7cf73c..0cadbc30a9f 100644
--- a/source/blender/python/intern/bpy_operator.c
+++ b/source/blender/python/intern/bpy_operator.c
@@ -384,7 +384,7 @@ static PyObject *pyop_dir(PyObject *UNUSED(self))
int i;
WM_operatortype_iter(&iter);
- list = PyList_New(BLI_ghash_size(iter.gh));
+ list = PyList_New(BLI_ghash_len(iter.gh));
for (i = 0; !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter), i++) {
wmOperatorType *ot = BLI_ghashIterator_getValue(&iter);
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index e220e6559a6..12cce685533 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -45,6 +45,7 @@
#include "BLI_utildefines.h"
#include "BPY_extern.h"
+#include "BPY_extern_clog.h"
#include "bpy_rna.h"
#include "bpy_rna_anim.h"
@@ -61,6 +62,8 @@
#include "RNA_define.h" /* RNA_def_property_free_identifier */
#include "RNA_access.h"
+#include "CLG_log.h"
+
#include "MEM_guardedalloc.h"
#include "BKE_main.h"
@@ -223,7 +226,7 @@ static PyObject *id_free_weakref_cb(PyObject *weakinfo_capsule, PyObject *weakre
GHash *weakinfo_hash = PyCapsule_GetPointer(weakinfo_capsule, NULL);
- if (BLI_ghash_size(weakinfo_hash) > 1) {
+ if (BLI_ghash_len(weakinfo_hash) > 1) {
BLI_ghash_remove(weakinfo_hash, weakref, NULL, NULL);
}
else { /* get the last id and free it */
@@ -243,7 +246,7 @@ static void id_release_weakref_list(struct ID *id, GHash *weakinfo_hash)
BLI_ghashIterator_init(&weakinfo_hash_iter, weakinfo_hash);
#ifdef DEBUG_RNA_WEAKREF
- fprintf(stdout, "id_release_weakref: '%s', %d items\n", id->name, BLI_ghash_size(weakinfo_hash));
+ fprintf(stdout, "id_release_weakref: '%s', %d items\n", id->name, BLI_ghash_len(weakinfo_hash));
#endif
while (!BLI_ghashIterator_done(&weakinfo_hash_iter)) {
@@ -266,7 +269,7 @@ static void id_release_weakref_list(struct ID *id, GHash *weakinfo_hash)
BLI_ghash_remove(id_weakref_pool, (void *)id, NULL, NULL);
BLI_ghash_free(weakinfo_hash, NULL, NULL);
- if (BLI_ghash_size(id_weakref_pool) == 0) {
+ if (BLI_ghash_len(id_weakref_pool) == 0) {
BLI_ghash_free(id_weakref_pool, NULL, NULL);
id_weakref_pool = NULL;
#ifdef DEBUG_RNA_WEAKREF
@@ -1418,10 +1421,11 @@ static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val)
const char *ptr_name = RNA_struct_name_get_alloc(ptr, NULL, 0, NULL);
/* prefer not fail silently in case of api errors, maybe disable it later */
- printf("RNA Warning: Current value \"%d\" "
- "matches no enum in '%s', '%s', '%s'\n",
- val, RNA_struct_identifier(ptr->type),
- ptr_name, RNA_property_identifier(prop));
+ CLOG_WARN(BPY_LOG_RNA,
+ "current value '%d' "
+ "matches no enum in '%s', '%s', '%s'",
+ val, RNA_struct_identifier(ptr->type),
+ ptr_name, RNA_property_identifier(prop));
#if 0 /* gives python decoding errors while generating docs :( */
char error_str[256];
@@ -6605,7 +6609,7 @@ static PyObject *pyrna_srna_ExternalType(StructRNA *srna)
if (bpy_types == NULL) {
PyErr_Print();
PyErr_Clear();
- fprintf(stderr, "%s: failed to find 'bpy_types' module\n", __func__);
+ CLOG_ERROR(BPY_LOG_RNA, "failed to find 'bpy_types' module");
return NULL;
}
bpy_types_dict = PyModule_GetDict(bpy_types); /* borrow */
@@ -6623,20 +6627,22 @@ static PyObject *pyrna_srna_ExternalType(StructRNA *srna)
PyObject *tp_slots = PyDict_GetItem(((PyTypeObject *)newclass)->tp_dict, bpy_intern_str___slots__);
if (tp_slots == NULL) {
- fprintf(stderr, "%s: expected class '%s' to have __slots__ defined\n\nSee bpy_types.py\n", __func__, idname);
+ CLOG_ERROR(BPY_LOG_RNA, "expected class '%s' to have __slots__ defined, see bpy_types.py", idname);
newclass = NULL;
}
else if (PyTuple_GET_SIZE(tp_bases)) {
PyObject *base = PyTuple_GET_ITEM(tp_bases, 0);
if (base_compare != base) {
- fprintf(stderr, "%s: incorrect subclassing of SRNA '%s'\nSee bpy_types.py\n", __func__, idname);
- PyC_ObSpit("Expected! ", base_compare);
+ char pyob_info[256];
+ PyC_ObSpitStr(pyob_info, sizeof(pyob_info), base_compare);
+ CLOG_ERROR(BPY_LOG_RNA,
+ "incorrect subclassing of SRNA '%s', expected '%s', see bpy_types.py",
+ idname, pyob_info);
newclass = NULL;
}
else {
- if (G.debug & G_DEBUG_PYTHON)
- fprintf(stderr, "SRNA Subclassed: '%s'\n", idname);
+ CLOG_INFO(BPY_LOG_RNA, 2, "SRNA sub-classed: '%s'", idname);
}
}
}
@@ -6734,7 +6740,7 @@ static PyObject *pyrna_srna_Subtype(StructRNA *srna)
}
else {
/* this should not happen */
- printf("%s: error registering '%s'\n", __func__, idname);
+ CLOG_ERROR(BPY_LOG_RNA, "failed to register '%s'", idname);
PyErr_Print();
PyErr_Clear();
}
@@ -6800,7 +6806,7 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr)
Py_DECREF(tp); /* srna owns, cant hold a ref */
}
else {
- fprintf(stderr, "%s: could not make type\n", __func__);
+ CLOG_WARN(BPY_LOG_RNA, "could not make type '%s'", RNA_struct_identifier(ptr->type));
pyrna = (BPy_StructRNA *) PyObject_GC_New(BPy_StructRNA, &pyrna_struct_Type);
#ifdef USE_WEAKREFS
pyrna->in_weakreflist = NULL;
@@ -7607,8 +7613,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
py_class = RNA_struct_py_type_get(ptr->type);
/* rare case. can happen when registering subclasses */
if (py_class == NULL) {
- fprintf(stderr, "%s: unable to get python class for rna struct '%.200s'\n",
- __func__, RNA_struct_identifier(ptr->type));
+ CLOG_WARN(BPY_LOG_RNA, "unable to get Python class for rna struct '%.200s'", RNA_struct_identifier(ptr->type));
return -1;
}
@@ -8257,6 +8262,43 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla
Py_RETURN_NONE;
}
+/* Access to 'owner_id' internal global. */
+
+static PyObject *pyrna_bl_owner_id_get(PyObject *UNUSED(self))
+{
+ const char *name = RNA_struct_state_owner_get();
+ if (name) {
+ return PyUnicode_FromString(name);
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *pyrna_bl_owner_id_set(PyObject *UNUSED(self), PyObject *value)
+{
+ const char *name;
+ if (value == Py_None) {
+ name = NULL;
+ }
+ else if (PyUnicode_Check(value)) {
+ name = _PyUnicode_AsString(value);
+ }
+ else {
+ PyErr_Format(PyExc_ValueError,
+ "owner_set(...): "
+ "expected None or a string, not '%.200s'", Py_TYPE(value)->tp_name);
+ return NULL;
+ }
+ RNA_struct_state_owner_set(name);
+ Py_RETURN_NONE;
+}
+
+PyMethodDef meth_bpy_owner_id_get = {
+ "_bl_owner_id_get", (PyCFunction)pyrna_bl_owner_id_get, METH_NOARGS, NULL,
+};
+PyMethodDef meth_bpy_owner_id_set = {
+ "_bl_owner_id_set", (PyCFunction)pyrna_bl_owner_id_set, METH_O, NULL,
+};
+
/* currently this is fairly limited, we would need to make some way to split up
* pyrna_callback_classmethod_... if we want more than one callback per type */
typedef struct BPyRNA_CallBack {
diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h
index f666294666e..32a63acde40 100644
--- a/source/blender/python/intern/bpy_rna.h
+++ b/source/blender/python/intern/bpy_rna.h
@@ -225,4 +225,8 @@ int pyrna_prop_validity_check(BPy_PropertyRNA *self);
extern PyMethodDef meth_bpy_register_class;
extern PyMethodDef meth_bpy_unregister_class;
+/* bpy.utils._bl_owner_(get/set) */
+extern PyMethodDef meth_bpy_owner_id_set;
+extern PyMethodDef meth_bpy_owner_id_get;
+
#endif
diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c
index e0ca3634261..ed9d1e9c0e5 100644
--- a/source/blender/python/intern/bpy_rna_array.c
+++ b/source/blender/python/intern/bpy_rna_array.c
@@ -28,6 +28,8 @@
#include <Python.h>
+#include "CLG_log.h"
+
#include "BLI_utildefines.h"
#include "RNA_types.h"
@@ -39,6 +41,8 @@
#include "RNA_access.h"
+#include "BPY_extern_clog.h"
+
#include "../generic/py_capi_utils.h"
#define USE_MATHUTILS
@@ -785,8 +789,7 @@ PyObject *pyrna_py_from_array_index(BPy_PropertyArrayRNA *self, PointerRNA *ptr,
len = RNA_property_multi_array_length(ptr, prop, arraydim);
if (index >= len || index < 0) {
/* this shouldn't happen because higher level funcs must check for invalid index */
- if (G.debug & G_DEBUG_PYTHON)
- printf("%s: invalid index %d for array with length=%d\n", __func__, index, len);
+ CLOG_WARN(BPY_LOG_RNA, "invalid index %d for array with length=%d", index, len);
PyErr_SetString(PyExc_IndexError, "out of range");
return NULL;
diff --git a/source/blender/python/intern/gpu_offscreen.c b/source/blender/python/intern/gpu_offscreen.c
index 91d407d18a8..72d338bd5db 100644
--- a/source/blender/python/intern/gpu_offscreen.c
+++ b/source/blender/python/intern/gpu_offscreen.c
@@ -37,8 +37,8 @@
#include "ED_screen.h"
-#include "GPU_compositing.h"
#include "GPU_framebuffer.h"
+#include "GPU_texture.h"
#include "../mathutils/mathutils.h"
@@ -89,7 +89,8 @@ PyDoc_STRVAR(pygpu_offscreen_color_texture_doc, "Color texture.\n\n:type: int");
static PyObject *pygpu_offscreen_color_texture_get(BPy_GPUOffScreen *self, void *UNUSED(type))
{
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
- return PyLong_FromLong(GPU_offscreen_color_texture(self->ofs));
+ GPUTexture *texture = GPU_offscreen_color_texture(self->ofs);
+ return PyLong_FromLong(GPU_texture_opengl_bindcode(texture));
}
PyDoc_STRVAR(pygpu_offscreen_bind_doc,
@@ -354,7 +355,7 @@ static PyObject *pygpu_offscreen_new(PyObject *UNUSED(self), PyObject *args, PyO
return NULL;
}
- ofs = GPU_offscreen_create(width, height, samples, false, err_out);
+ ofs = GPU_offscreen_create(width, height, samples, true, false, err_out);
if (ofs == NULL) {
PyErr_Format(PyExc_RuntimeError,
diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c
index 9492b6d67f3..026384743bd 100644
--- a/source/blender/python/mathutils/mathutils_Euler.c
+++ b/source/blender/python/mathutils/mathutils_Euler.c
@@ -689,6 +689,8 @@ PyDoc_STRVAR(euler_doc,
"\n"
" This object gives access to Eulers in Blender.\n"
"\n"
+" .. seealso:: `Euler angles <https://en.wikipedia.org/wiki/Euler_angles>`__ on Wikipedia.\n"
+"\n"
" :param angles: Three angles, in radians.\n"
" :type angles: 3d vector\n"
" :param order: Optional order of the angles, a permutation of ``XYZ``.\n"
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index 924e46a8c00..cc6a5367895 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -1710,10 +1710,18 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args)
/* TODO, different sized matrix */
if (self->num_col == 4 && self->num_row == 4) {
+#ifdef MATH_STANDALONE
+ blend_m4_m4m4((float (*)[4])mat, (float (*)[4])self->matrix, (float (*)[4])mat2->matrix, fac);
+#else
interp_m4_m4m4((float (*)[4])mat, (float (*)[4])self->matrix, (float (*)[4])mat2->matrix, fac);
+#endif
}
else if (self->num_col == 3 && self->num_row == 3) {
+#ifdef MATH_STANDALONE
+ blend_m3_m3m3((float (*)[3])mat, (float (*)[3])self->matrix, (float (*)[3])mat2->matrix, fac);
+#else
interp_m3_m3m3((float (*)[3])mat, (float (*)[3])self->matrix, (float (*)[3])mat2->matrix, fac);
+#endif
}
else {
PyErr_SetString(PyExc_ValueError,
diff --git a/source/blender/python/mathutils/mathutils_bvhtree.c b/source/blender/python/mathutils/mathutils_bvhtree.c
index ba0b6eb11a5..88195700a50 100644
--- a/source/blender/python/mathutils/mathutils_bvhtree.c
+++ b/source/blender/python/mathutils/mathutils_bvhtree.c
@@ -33,7 +33,7 @@
#include "BLI_utildefines.h"
#include "BLI_kdopbvh.h"
-#include "BLI_polyfill2d.h"
+#include "BLI_polyfill_2d.h"
#include "BLI_math.h"
#include "BLI_ghash.h"
#include "BLI_memarena.h"
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index 72f92d210d7..d935949fd8c 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -34,8 +34,8 @@
#ifndef MATH_STANDALONE /* define when building outside blender */
# include "MEM_guardedalloc.h"
# include "BLI_blenlib.h"
-# include "BLI_boxpack2d.h"
-# include "BLI_convexhull2d.h"
+# include "BLI_boxpack_2d.h"
+# include "BLI_convexhull_2d.h"
# include "BKE_displist.h"
# include "BKE_curve.h"
#endif
@@ -742,7 +742,7 @@ static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObjec
float lambda;
PyObject *ret;
int size = 2;
-
+
if (!PyArg_ParseTuple(
args, "OOO:intersect_point_line",
&py_pt, &py_line_a, &py_line_b))
@@ -760,7 +760,7 @@ static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObjec
/* do the calculation */
lambda = closest_to_line_v3(pt_out, pt, line_a, line_b);
-
+
ret = PyTuple_New(2);
PyTuple_SET_ITEMS(ret,
Vector_CreatePyObject(pt_out, size, NULL),
@@ -882,7 +882,7 @@ static PyObject *M_Geometry_intersect_point_quad_2d(PyObject *UNUSED(self), PyOb
PyObject *py_pt, *py_quad[4];
float pt[2], quad[4][2];
int i;
-
+
if (!PyArg_ParseTuple(
args, "OOOOO:intersect_point_quad_2d",
&py_pt, UNPACK4_EX(&, py_quad, )))
@@ -954,12 +954,12 @@ PyDoc_STRVAR(M_Geometry_barycentric_transform_doc,
" :type tri_a2: :class:`mathutils.Vector`\n"
" :arg tri_a3: source triangle vertex.\n"
" :type tri_a3: :class:`mathutils.Vector`\n"
-" :arg tri_a1: target triangle vertex.\n"
-" :type tri_a1: :class:`mathutils.Vector`\n"
-" :arg tri_a2: target triangle vertex.\n"
-" :type tri_a2: :class:`mathutils.Vector`\n"
-" :arg tri_a3: target triangle vertex.\n"
-" :type tri_a3: :class:`mathutils.Vector`\n"
+" :arg tri_b1: target triangle vertex.\n"
+" :type tri_b1: :class:`mathutils.Vector`\n"
+" :arg tri_b2: target triangle vertex.\n"
+" :type tri_b2: :class:`mathutils.Vector`\n"
+" :arg tri_b3: target triangle vertex.\n"
+" :type tri_b3: :class:`mathutils.Vector`\n"
" :return: The transformed point\n"
" :rtype: :class:`mathutils.Vector`'s\n"
);
diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h
index 60ffd8f42e4..d5230f74316 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -39,7 +39,10 @@
struct bNode;
struct bNodeTree;
+struct BakePixel;
+struct Depsgraph;
struct Depsgraph;
+struct EvaluationContext;
struct IDProperty;
struct Main;
struct Object;
@@ -51,7 +54,7 @@ struct RenderLayer;
struct RenderResult;
struct ReportList;
struct Scene;
-struct BakePixel;
+struct ViewLayer;
/* External Engine */
@@ -92,9 +95,10 @@ typedef struct RenderEngineType {
char name[64];
int flag;
- void (*update)(struct RenderEngine *engine, struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene);
+ void (*update)(struct RenderEngine *engine, struct Main *bmain, struct Scene *scene);
void (*render_to_image)(struct RenderEngine *engine, struct Depsgraph *depsgraph);
- void (*bake)(struct RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type,
+ void (*bake)(struct RenderEngine *engine, struct Depsgraph *depsgraph,
+ struct Scene *scene, struct Object *object, const int pass_type,
const int pass_filter, const int object_id, const struct BakePixel *pixel_array, const int num_pixels,
const int depth, void *result);
@@ -132,6 +136,9 @@ typedef struct RenderEngine {
struct ReportList *reports;
+ /* Depsgraph */
+ struct Depsgraph *depsgraph;
+
/* for blender internal only */
int update_flag;
int job_update_flag;
@@ -183,14 +190,14 @@ void RE_engines_init(void);
void RE_engines_exit(void);
void RE_engines_register(struct Main *bmain, RenderEngineType *render_type);
+bool RE_engine_is_opengl(RenderEngineType *render_type);
+
RenderEngineType *RE_engines_find(const char *idname);
rcti* RE_engine_get_current_tiles(struct Render *re, int *r_total_tiles, bool *r_needs_free);
struct RenderData *RE_engine_get_render_data(struct Render *re);
void RE_bake_engine_set_engine_parameters(
- struct Render *re, struct Main *bmain, struct Depsgraph *graph, struct Scene *scene);
-
-struct ViewLayer *RE_engine_get_view_layer(struct Render *re);
+ struct Render *re, struct Main *bmain, struct Scene *scene);
#endif /* __RE_ENGINE_H__ */
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 0557efccc2f..c5e8443374a 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -34,6 +34,7 @@
#include "DNA_listBase.h"
#include "DNA_vec_types.h"
+#include "DEG_depsgraph.h"
struct bMovieHandle;
struct bNodeTree;
@@ -121,7 +122,9 @@ typedef struct RenderLayer {
/* optional saved endresult on disk */
void *exrhandle;
-
+
+ struct EvaluationContext eval_ctx;
+
ListBase passes;
} RenderLayer;
@@ -235,6 +238,8 @@ void RE_render_result_rect_from_ibuf(
struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name);
float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, const char *name, const char *viewname);
+bool RE_HasSingleLayer(struct Render *re);
+
/* add passes for grease pencil */
struct RenderPass *RE_create_gp_pass(struct RenderResult *rr, const char *layername, const char *viewname);
@@ -250,7 +255,6 @@ void RE_ChangeModeFlag(struct Render *re, int flag, bool clear);
struct Object *RE_GetCamera(struct Render *re); /* return camera override if set */
void RE_SetOverrideCamera(struct Render *re, struct Object *camera);
void RE_SetCamera(struct Render *re, struct Object *camera);
-void RE_SetDepsgraph(struct Render *re, struct Depsgraph *graph);
void RE_SetEnvmapCamera(struct Render *re, struct Object *cam_ob, float viewscale, float clipsta, float clipend);
void RE_SetWindow(struct Render *re, const rctf *viewplane, float clipsta, float clipend);
void RE_SetOrtho(struct Render *re, const rctf *viewplane, float clipsta, float clipend);
@@ -267,7 +271,10 @@ void RE_GetViewPlane(struct Render *re, rctf *r_viewplane, rcti *r_disprect);
void RE_Database_FromScene(
struct Render *re, struct Main *bmain, struct Scene *scene,
unsigned int lay, int use_camera_view);
-void RE_Database_Preprocess(struct Render *re);
+void RE_Database_CameraOnly(
+ struct Render *re, struct Main *bmain, struct Scene *scene,
+ unsigned int lay, int use_camera_view);
+void RE_Database_Preprocess(struct EvaluationContext *eavl_ctx, struct Render *re);
void RE_Database_Free(struct Render *re);
/* project dbase again, when viewplane/perspective changed */
@@ -337,10 +344,6 @@ void RE_current_scene_update_cb(struct Render *re, void *handle, void (*f)(void
/* should move to kernel once... still unsure on how/where */
float RE_filter_value(int type, float x);
-/* vector blur zbuffer method */
-void RE_zbuf_accumulate_vecblur(
- struct NodeBlurData *nbd, int xsize, int ysize, float *newrect,
- const float *imgrect, float *vecbufrect, const float *zbufrect);
int RE_seq_render_active(struct Scene *scene, struct RenderData *rd);
@@ -368,14 +371,13 @@ struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int pas
#define RE_BAKE_VERTEX_COLORS 14
void RE_Database_Baking(
- struct Render *re, struct Main *bmain, struct Scene *scene,
+ struct Render *re, struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer,
unsigned int lay, const int type, struct Object *actob);
void RE_DataBase_GetView(struct Render *re, float mat[4][4]);
void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, float mat[4][4]);
void RE_GetCameraModelMatrix(struct Render *re, struct Object *camera, float r_mat[4][4]);
struct Scene *RE_GetScene(struct Render *re);
-struct EvaluationContext *RE_GetEvalCtx(struct Render *re);
bool RE_force_single_renderlayer(struct Scene *scene);
bool RE_is_rendering_allowed(struct Scene *scene, struct Object *camera_override, 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 17b321fd3b4..0021687efbd 100644
--- a/source/blender/render/extern/include/RE_render_ext.h
+++ b/source/blender/render/extern/include/RE_render_ext.h
@@ -38,6 +38,7 @@
/* called by meshtools */
struct DerivedMesh;
+struct EvaluationContext;
struct ImagePool;
struct MTex;
struct Scene;
@@ -55,7 +56,7 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen
void RE_texture_rng_init(void);
void RE_texture_rng_exit(void);
-struct Material *RE_sample_material_init(struct Material *orig_mat, struct Scene *scene);
+struct Material *RE_sample_material_init(const struct EvaluationContext *eval_ctx, struct Material *orig_mat, struct Scene *scene);
void RE_sample_material_free(struct Material *mat);
void RE_sample_material_color(
struct Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3],
@@ -64,34 +65,24 @@ void RE_sample_material_color(
/* imagetexture.c */
void ibuf_sample(struct ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4]);
-/* zbuf.c */
-void antialias_tagbuf(int xsize, int ysize, char *rectmove);
-
/* pointdensity.c */
struct PointDensity;
void RE_point_density_cache(
- struct Scene *scene,
- struct ViewLayer *view_layer,
- struct PointDensity *pd,
- const bool use_render_params);
+ const struct EvaluationContext *eval_ctx,
+ struct PointDensity *pd);
void RE_point_density_minmax(
- struct Scene *scene,
- struct ViewLayer *view_layer,
+ const struct EvaluationContext *eval_ctx,
struct PointDensity *pd,
- const bool use_render_params,
float r_min[3], float r_max[3]);
void RE_point_density_sample(
- struct Scene *scene,
- struct ViewLayer *view_layer,
+ const struct EvaluationContext *eval_ctx,
struct PointDensity *pd,
const int resolution,
- const bool use_render_params,
float *values);
void RE_point_density_free(struct PointDensity *pd);
#endif /* __RE_RENDER_EXT_H__ */
-
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index 0b392c122db..281f0082d7f 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -215,7 +215,7 @@ int multitex_nodes(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3],
const short thread, short which_output, struct ShadeInput *shi, struct MTex *mtex,
struct ImagePool *pool);
float RE_lamp_get_data(struct ShadeInput *shi, struct Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4]);
-void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]);
+void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *random, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]);
float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta);
diff --git a/source/blender/render/intern/include/pointdensity.h b/source/blender/render/intern/include/pointdensity.h
index 1d1e808e8d3..f122b3dc4c1 100644
--- a/source/blender/render/intern/include/pointdensity.h
+++ b/source/blender/render/intern/include/pointdensity.h
@@ -37,13 +37,14 @@
* Make point density kd-trees for all point density textures in the scene
*/
+struct EvaluationContext;
struct PointDensity;
struct Render;
struct TexResult;
void free_pointdensity(struct PointDensity *pd);
-void cache_pointdensity(struct Render *re, struct PointDensity *pd);
-void make_pointdensities(struct Render *re);
+void cache_pointdensity(const struct EvaluationContext *eval_ctx, struct Render *re, struct PointDensity *pd);
+void make_pointdensities(const struct EvaluationContext *eval_ctx, struct Render *re);
void free_pointdensities(struct Render *re);
int pointdensitytex(struct Tex *tex, const float texvec[3], struct TexResult *texres);
diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h
index 8d293c938c7..03292579d90 100644
--- a/source/blender/render/intern/include/render_result.h
+++ b/source/blender/render/intern/include/render_result.h
@@ -117,5 +117,28 @@ void render_result_views_shallowcopy(struct RenderResult *dst, struct RenderResu
void render_result_views_shallowdelete(struct RenderResult *rr);
bool render_result_has_views(struct RenderResult *rr);
+#define FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re_, iter_) \
+{ \
+ int nr_; \
+ ViewLayer *iter_; \
+ for (nr_ = 0, iter_ = (re_)->view_layers.first; \
+ iter_ != NULL; \
+ iter_ = iter_->next, nr_++) \
+ { \
+ if ((re_)->r.scemode & R_SINGLE_LAYER) { \
+ if (nr_ != re->active_view_layer) { \
+ continue; \
+ } \
+ } \
+ else { \
+ if ((iter_->flag & VIEW_LAYER_RENDER) == 0) { \
+ continue; \
+ } \
+ }
+
+#define FOREACH_VIEW_LAYER_TO_RENDER_END \
+ } \
+} ((void)0)
+
#endif /* __RENDER_RESULT_H__ */
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index d24aae6ac97..2c46138c7ea 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -185,8 +185,6 @@ struct Render {
/* shadow counter, detect shadow-reuse for shaders */
int shadowsamplenr[BLENDER_MAX_THREADS];
-
- struct Depsgraph *depsgraph;
/* main, scene, and its full copy of renderdata and world */
struct Main *main;
@@ -280,7 +278,6 @@ struct Render {
struct ReportList *reports;
struct ImagePool *pool;
- struct EvaluationContext *eval_ctx;
void **movie_ctx_arr;
char viewname[MAX_NAME];
diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h
index b576d69d806..1d1af7092c8 100644
--- a/source/blender/render/intern/include/renderdatabase.h
+++ b/source/blender/render/intern/include/renderdatabase.h
@@ -40,6 +40,7 @@ extern "C" {
struct Object;
struct VlakRen;
struct VertRen;
+struct EvaluationContext;
struct HaloRen;
struct Main;
struct Material;
@@ -164,7 +165,7 @@ void area_lamp_vectors(struct LampRen *lar);
/* convertblender.c */
void init_render_world(Render *re);
-void RE_Database_FromScene_Vectors(Render *re, struct Main *bmain, struct Scene *sce, unsigned int lay);
+void RE_Database_FromScene_Vectors(struct EvaluationContext *eval_ctx, Render *re, struct Main *bmain, struct Scene *sce, unsigned int lay);
#ifdef __cplusplus
}
diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c
index 71a595d6a8b..48f5f494e58 100644
--- a/source/blender/render/intern/source/bake.c
+++ b/source/blender/render/intern/source/bake.c
@@ -609,7 +609,7 @@ static int get_next_bake_face(BakeShade *bs)
return 0;
}
- BLI_lock_thread(LOCK_CUSTOM1);
+ BLI_thread_lock(LOCK_CUSTOM1);
for (; obi; obi = obi->next, v = 0) {
obr = obi->obr;
@@ -725,13 +725,13 @@ static int get_next_bake_face(BakeShade *bs)
bs->vlr = vlr;
bs->vdone++; /* only for error message if nothing was rendered */
v++;
- BLI_unlock_thread(LOCK_CUSTOM1);
+ BLI_thread_unlock(LOCK_CUSTOM1);
return 1;
}
}
}
- BLI_unlock_thread(LOCK_CUSTOM1);
+ BLI_thread_unlock(LOCK_CUSTOM1);
return 0;
}
@@ -846,7 +846,7 @@ static void shade_tface(BakeShade *bs)
if (bs->use_mask || bs->use_displacement_buffer) {
BakeImBufuserData *userdata = bs->ibuf->userdata;
if (userdata == NULL) {
- BLI_lock_thread(LOCK_CUSTOM1);
+ BLI_thread_lock(LOCK_CUSTOM1);
userdata = bs->ibuf->userdata;
if (userdata == NULL) /* since the thread was locked, its possible another thread alloced the value */
userdata = MEM_callocN(sizeof(BakeImBufuserData), "BakeImBufuserData");
@@ -865,7 +865,7 @@ static void shade_tface(BakeShade *bs)
bs->ibuf->userdata = userdata;
- BLI_unlock_thread(LOCK_CUSTOM1);
+ BLI_thread_unlock(LOCK_CUSTOM1);
}
bs->rect_mask = userdata->mask_buffer;
@@ -1041,7 +1041,7 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
BKE_main_id_tag_listbase(&G.main->mesh, LIB_TAG_DOIT, false);
}
- BLI_init_threads(&threads, do_bake_thread, re->r.threads);
+ BLI_threadpool_init(&threads, do_bake_thread, re->r.threads);
handles = MEM_callocN(sizeof(BakeShade) * re->r.threads, "BakeShade");
@@ -1078,7 +1078,7 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
handles[a].displacement_min = FLT_MAX;
handles[a].displacement_max = -FLT_MAX;
- BLI_insert_thread(&threads, &handles[a]);
+ BLI_threadpool_insert(&threads, &handles[a]);
}
/* wait for everything to be done */
@@ -1152,7 +1152,7 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
MEM_freeN(handles);
- BLI_end_threads(&threads);
+ BLI_threadpool_end(&threads);
if (vdone == 0) {
result = BAKE_RESULT_NO_OBJECTS;
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 19a87784ad4..c358f0388a4 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -56,7 +56,7 @@
#include "DNA_modifier_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_fluidsim.h"
+#include "DNA_object_fluidsim_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
@@ -84,6 +84,7 @@
#include "BKE_scene.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
#include "PIL_time.h"
@@ -1291,7 +1292,8 @@ static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int
}
}
}
-static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys, int timeoffset)
+static int render_new_particle_system(const EvaluationContext *eval_ctx, Render *re,
+ ObjectRen *obr, ParticleSystem *psys, int timeoffset)
{
Object *ob= obr->ob;
// Object *tob=0;
@@ -1315,10 +1317,10 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
float strandlen=0.0f, curlen=0.0f;
float hasize, pa_size, r_tilt, r_length;
float pa_time, pa_birthtime, pa_dietime;
- float random, simplify[2], pa_co[3];
+ float random, pa_co[3];
const float cfra= BKE_scene_frame_get(re->scene);
int i, a, k, max_k=0, totpart;
- bool do_simplify = false, do_surfacecache = false, use_duplimat = false;
+ bool do_surfacecache = false, use_duplimat = false;
int totchild=0, step_nbr;
int seed, path_nbr=0, orco1=0, num;
int totface;
@@ -1352,7 +1354,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if (!(psmd->modifier.mode & eModifierMode_Render))
return 0;
- sim.eval_ctx = re->eval_ctx;
+ sim.eval_ctx = eval_ctx;
sim.scene = re->scene;
sim.ob = ob;
sim.psys = psys;
@@ -1633,8 +1635,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
get_particle_uvco_mcol(part->from, psmd->dm_final, parent->fuv, num, &sd);
}
- do_simplify = psys_render_simplify_params(psys, cpa, simplify);
-
if (strandbuf) {
int orignum = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, cpa->num) : cpa->num;
@@ -1667,12 +1667,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
strand->vert= svert;
copy_v3_v3(strand->orco, sd.orco);
- if (do_simplify) {
- float *ssimplify= RE_strandren_get_simplify(obr, strand, 1);
- ssimplify[0]= simplify[0];
- ssimplify[1]= simplify[1];
- }
-
if (sd.surfnor) {
float *snor= RE_strandren_get_surfnor(obr, strand, 1);
copy_v3_v3(snor, sd.surfnor);
@@ -2177,7 +2171,7 @@ static void displace(Render *re, ObjectRen *obr)
/* Metaball */
/* ------------------------------------------------------------------------- */
-static void init_render_mball(Render *re, ObjectRen *obr)
+static void init_render_mball(const EvaluationContext *eval_ctx, Render *re, ObjectRen *obr)
{
Object *ob= obr->ob;
DispList *dl;
@@ -2203,7 +2197,7 @@ static void init_render_mball(Render *re, ObjectRen *obr)
need_orco= 1;
}
- BKE_displist_make_mball_forRender(re->eval_ctx, re->scene, ob, &dispbase);
+ BKE_displist_make_mball_forRender(eval_ctx, re->scene, ob, &dispbase);
dl= dispbase.first;
if (dl == NULL) return;
@@ -2570,7 +2564,7 @@ static void init_render_dm(DerivedMesh *dm, Render *re, ObjectRen *obr,
}
-static void init_render_surf(Render *re, ObjectRen *obr, int timeoffset)
+static void init_render_surf(const EvaluationContext *eval_ctx, Render *re, ObjectRen *obr, int timeoffset)
{
Object *ob= obr->ob;
Nurb *nu = NULL;
@@ -2603,13 +2597,13 @@ static void init_render_surf(Render *re, ObjectRen *obr, int timeoffset)
if (ob->parent && (ob->parent->type==OB_LATTICE)) need_orco= 1;
- BKE_displist_make_surf(re->eval_ctx, re->scene, ob, &displist, &dm, 1, 0, 1);
+ BKE_displist_make_surf(eval_ctx, re->scene, ob, &displist, &dm, 1, 0, 1);
if (dm) {
if (need_orco) {
orco = get_object_orco(re, ob);
if (!orco) {
- orco= BKE_displist_make_orco(re->eval_ctx, re->scene, ob, dm, true, true);
+ orco= BKE_displist_make_orco(eval_ctx, re->scene, ob, dm, true, true);
if (orco) {
set_object_orco(re, ob, orco);
}
@@ -2641,7 +2635,7 @@ static void init_render_surf(Render *re, ObjectRen *obr, int timeoffset)
MEM_freeN(matar);
}
-static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
+static void init_render_curve(const EvaluationContext *eval_ctx, Render *re, ObjectRen *obr, int timeoffset)
{
Object *ob= obr->ob;
Curve *cu;
@@ -2661,7 +2655,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
if (ob->type==OB_FONT && cu->str==NULL) return;
else if (ob->type==OB_CURVE && cu->nurb.first==NULL) return;
- BKE_displist_make_curveTypes_forRender(re->eval_ctx, re->scene, ob, &disp, &dm, false, true);
+ BKE_displist_make_curveTypes_forRender(eval_ctx, re->scene, ob, &disp, &dm, false, true);
dl= disp.first;
if (dl==NULL) return;
@@ -2688,7 +2682,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
if (need_orco) {
orco = get_object_orco(re, ob);
if (!orco) {
- orco = BKE_displist_make_orco(re->eval_ctx, re->scene, ob, dm, true, true);
+ orco = BKE_displist_make_orco(eval_ctx, re->scene, ob, dm, true, true);
if (orco) {
set_object_orco(re, ob, orco);
}
@@ -2702,7 +2696,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
if (need_orco) {
orco = get_object_orco(re, ob);
if (!orco) {
- orco = BKE_curve_make_orco(re->eval_ctx, re->scene, ob, NULL);
+ orco = BKE_curve_make_orco(eval_ctx, re->scene, ob, NULL);
set_object_orco(re, ob, orco);
}
}
@@ -3113,7 +3107,7 @@ static bool has_freestyle_edge_mark(EdgeHash *edge_hash, int v1, int v2)
}
#endif
-static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
+static void init_render_mesh(const EvaluationContext *eval_ctx, Render *re, ObjectRen *obr, int timeoffset)
{
Object *ob= obr->ob;
Mesh *me;
@@ -3202,9 +3196,9 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
#endif
if (re->r.scemode & R_VIEWPORT_PREVIEW)
- dm= mesh_create_derived_view(re->eval_ctx, re->scene, ob, mask);
+ dm= mesh_create_derived_view(eval_ctx, re->scene, ob, mask);
else
- dm= mesh_create_derived_render(re->eval_ctx, re->scene, ob, mask);
+ dm= mesh_create_derived_render(eval_ctx, re->scene, ob, mask);
if (dm==NULL) return; /* in case duplicated object fails? */
mvert= dm->getVertArray(dm);
@@ -3986,7 +3980,7 @@ static void add_lightgroup(Render *re, Group *group, int exclusive)
#if 0
/* it's a bit too many loops in loops... but will survive */
/* note that 'exclusive' will remove it from the global list */
- FOREACH_GROUP_BASE(group, base)
+ FOREACH_GROUP_BASE_BEGIN(group, base)
{
Object *object = base->object;
@@ -4014,7 +4008,7 @@ static void add_lightgroup(Render *re, Group *group, int exclusive)
}
}
}
- FOREACH_GROUP_BASE_END
+ FOREACH_GROUP_BASE_END;
#else
UNUSED_VARS(re, exclusive);
#endif
@@ -4607,7 +4601,7 @@ static void set_dupli_tex_mat(Render *re, ObjectInstanceRen *obi, DupliObject *d
copy_v2_v2(obi->dupliuv, dob->uv);
}
-static void init_render_object_data(Render *re, ObjectRen *obr, int timeoffset)
+static void init_render_object_data(const EvaluationContext *eval_ctx, Render *re, ObjectRen *obr, int timeoffset)
{
Object *ob= obr->ob;
ParticleSystem *psys;
@@ -4621,26 +4615,26 @@ static void init_render_object_data(Render *re, ObjectRen *obr, int timeoffset)
const CustomDataMask mask = CD_MASK_RENDER_INTERNAL;
if (re->r.scemode & R_VIEWPORT_PREVIEW)
- dm = mesh_create_derived_view(re->eval_ctx, re->scene, ob, mask);
+ dm = mesh_create_derived_view(eval_ctx, re->scene, ob, mask);
else
- dm = mesh_create_derived_render(re->eval_ctx, re->scene, ob, mask);
+ dm = mesh_create_derived_render(eval_ctx, re->scene, ob, mask);
dm->release(dm);
}
for (psys=ob->particlesystem.first, i=0; i<obr->psysindex-1; i++)
psys= psys->next;
- render_new_particle_system(re, obr, psys, timeoffset);
+ render_new_particle_system(eval_ctx, re, obr, psys, timeoffset);
}
else {
if (ELEM(ob->type, OB_FONT, OB_CURVE))
- init_render_curve(re, obr, timeoffset);
+ init_render_curve(eval_ctx, re, obr, timeoffset);
else if (ob->type==OB_SURF)
- init_render_surf(re, obr, timeoffset);
+ init_render_surf(eval_ctx, re, obr, timeoffset);
else if (ob->type==OB_MESH)
- init_render_mesh(re, obr, timeoffset);
+ init_render_mesh(eval_ctx, re, obr, timeoffset);
else if (ob->type==OB_MBALL)
- init_render_mball(re, obr);
+ init_render_mball(eval_ctx, re, obr);
}
finalize_render_object(re, obr, timeoffset);
@@ -4651,7 +4645,8 @@ static void init_render_object_data(Render *re, ObjectRen *obr, int timeoffset)
re->totstrand += obr->totstrand;
}
-static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *dob, float omat[4][4], int timeoffset)
+static void add_render_object(const EvaluationContext *eval_ctx, Render *re, Object *ob, Object *par, DupliObject *dob,
+ float omat[4][4], int timeoffset)
{
ObjectRen *obr;
ObjectInstanceRen *obi;
@@ -4660,22 +4655,10 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
index= (dob)? dob->persistent_id[0]: 0;
- /* It seems that we may generate psys->renderdata recursively in some nasty intricated cases of
- * several levels of bupliobject (see T51524).
- * For now, basic rule is, do not restore psys if it was already in 'render state'.
- * Another, more robust solution could be to add some reference counting to that renderdata... */
- bool psys_has_renderdata = false;
-
/* the emitter has to be processed first (render levels of modifiers) */
/* so here we only check if the emitter should be rendered */
if (ob->particlesystem.first) {
show_emitter = (ob->duplicator_visibility_flag & OB_DUPLI_FLAG_RENDER) != 0;
- for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- if (!(re->r.scemode & R_VIEWPORT_PREVIEW)) {
- psys_has_renderdata |= (psys->renderdata != NULL);
- psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset);
- }
- }
/* if no psys has "show emitter" selected don't render emitter */
if (show_emitter == 0)
@@ -4689,7 +4672,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
obr->flag |= R_INSTANCEABLE;
copy_m4_m4(obr->obmat, ob->obmat);
}
- init_render_object_data(re, obr, timeoffset);
+ init_render_object_data(eval_ctx, re, obr, timeoffset);
/* only add instance for objects that have not been used for dupli */
if (!(ob->transflag & OB_RENDER_DUPLI)) {
@@ -4720,10 +4703,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
}
if (dob)
psys->flag |= PSYS_USE_IMAT;
- init_render_object_data(re, obr, timeoffset);
- if (!(re->r.scemode & R_VIEWPORT_PREVIEW) && !psys_has_renderdata) {
- psys_render_restore(ob, psys);
- }
+ init_render_object_data(eval_ctx, re, obr, timeoffset);
psys->flag &= ~PSYS_USE_IMAT;
/* only add instance for objects that have not been used for dupli */
@@ -4739,7 +4719,8 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
/* par = pointer to duplicator parent, needed for object lookup table */
/* index = when duplicater copies same object (particle), the counter */
-static void init_render_object(Render *re, Object *ob, Object *par, DupliObject *dob, float omat[4][4], int timeoffset)
+static void init_render_object(const EvaluationContext *eval_ctx, Render *re, Object *ob, Object *par, DupliObject *dob,
+ float omat[4][4], int timeoffset)
{
static double lasttime= 0.0;
double time;
@@ -4748,7 +4729,7 @@ static void init_render_object(Render *re, Object *ob, Object *par, DupliObject
if (ob->type==OB_LAMP)
add_render_lamp(re, ob);
else if (render_object_type(ob->type))
- add_render_object(re, ob, par, dob, omat, timeoffset);
+ add_render_object(eval_ctx, re, ob, par, dob, omat, timeoffset);
else {
mul_m4_m4m4(mat, re->viewmat, ob->obmat);
invert_m4_m4(ob->imat, mat);
@@ -4904,81 +4885,39 @@ static int allow_render_dupli_instance(Render *UNUSED(re), DupliObject *dob, Obj
(!(dob->type == OB_DUPLIGROUP) || !dob->animated));
}
-static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, int level, int enable)
-{
- /* ugly function, but we need to set particle systems to their render
- * settings before calling object_duplilist, to get render level duplis */
- ParticleSystem *psys;
- DerivedMesh *dm;
-
- if (re->r.scemode & R_VIEWPORT_PREVIEW)
- return;
-
- if (level >= MAX_DUPLI_RECUR)
- return;
-
- if (ob->transflag & OB_DUPLIPARTS) {
- for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- if (ELEM(psys->part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
- if (enable)
- psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset);
- else
- psys_render_restore(ob, psys);
- }
- }
-
- if (enable) {
- /* this is to make sure we get render level duplis in groups:
- * the derivedmesh must be created before init_render_mesh,
- * since object_duplilist does dupliparticles before that */
- dm = mesh_create_derived_render(re->eval_ctx, re->scene, ob, CD_MASK_RENDER_INTERNAL);
- dm->release(dm);
-
- for (psys=ob->particlesystem.first; psys; psys=psys->next)
- psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated;
- }
- }
-
- if (ob->dup_group == NULL) return;
-
- FOREACH_GROUP_OBJECT(ob->dup_group, object)
- {
- dupli_render_particle_set(re, object, timeoffset, level+1, enable);
- }
- FOREACH_GROUP_OBJECT_END
-}
-
static int get_vector_viewlayers(Scene *UNUSED(sce))
{
return 0;
}
-static void add_group_render_dupli_obs(Render *re, Group *group, int nolamps, int onlyselected, Object *actob, int timeoffset, int level)
+static void add_group_render_dupli_obs(const EvaluationContext *eval_ctx, Render *re, Group *group, int nolamps,
+ int onlyselected, Object *actob, int timeoffset, int level)
{
/* Simple preventing of too deep nested groups. */
if (level > MAX_DUPLI_RECUR) return;
/* Recursively go into dupligroups to find objects with OB_RENDER_DUPLI
* that were not created yet. */
- FOREACH_GROUP_OBJECT(group, ob)
+ FOREACH_GROUP_OBJECT_BEGIN(group, ob)
{
if (ob->flag & OB_DONE) {
if (ob->transflag & OB_RENDER_DUPLI) {
if (allow_render_object(re, ob, nolamps, onlyselected, actob)) {
- init_render_object(re, ob, NULL, NULL, NULL, timeoffset);
+ init_render_object(eval_ctx, re, ob, NULL, NULL, NULL, timeoffset);
ob->transflag &= ~OB_RENDER_DUPLI;
if (ob->dup_group) {
- add_group_render_dupli_obs(re, ob->dup_group, nolamps, onlyselected, actob, timeoffset, level+1);
+ add_group_render_dupli_obs(eval_ctx, re, ob->dup_group, nolamps, onlyselected, actob, timeoffset, level+1);
}
}
}
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
-static void database_init_objects(Render *re, unsigned int UNUSED(renderlay), int nolamps, int onlyselected, Object *actob, int timeoffset)
+static void database_init_objects(const EvaluationContext *eval_ctx, Render *re, unsigned int UNUSED(renderlay),
+ int nolamps, int onlyselected, Object *actob, int timeoffset)
{
Base *base;
Object *ob;
@@ -5031,7 +4970,7 @@ static void database_init_objects(Render *re, unsigned int UNUSED(renderlay), in
* it still needs to create the ObjectRen containing the data */
if (ob->transflag & OB_RENDER_DUPLI) {
if (allow_render_object(re, ob, nolamps, onlyselected, actob)) {
- init_render_object(re, ob, NULL, NULL, NULL, timeoffset);
+ init_render_object(eval_ctx, re, ob, NULL, NULL, NULL, timeoffset);
ob->transflag &= ~OB_RENDER_DUPLI;
}
}
@@ -5045,12 +4984,8 @@ static void database_init_objects(Render *re, unsigned int UNUSED(renderlay), in
/* create list of duplis generated by this object, particle
* system need to have render settings set for dupli particles */
- dupli_render_particle_set(re, ob, timeoffset, 0, 1);
- duplilist = object_duplilist(re->eval_ctx, re->scene, ob);
- duplilist_apply_data = duplilist_apply(re->eval_ctx, ob, NULL, duplilist);
- /* postpone 'dupli_render_particle_set', since RE_addRenderInstance reads
- * index values from 'dob->persistent_id[0]', referencing 'psys->child' which
- * may be smaller once the particle system is restored, see: T45563. */
+ duplilist = object_duplilist(eval_ctx, re->scene, ob);
+ duplilist_apply_data = duplilist_apply(eval_ctx, ob, NULL, duplilist);
for (dob= duplilist->first, i = 0; dob; dob= dob->next, ++i) {
DupliExtraData *dob_extra = &duplilist_apply_data->extra[i];
@@ -5130,7 +5065,7 @@ static void database_init_objects(Render *re, unsigned int UNUSED(renderlay), in
if (obi==NULL)
/* can't instance, just create the object */
- init_render_object(re, obd, ob, dob, dob_extra->obmat, timeoffset);
+ init_render_object(eval_ctx, re, obd, ob, dob, dob_extra->obmat, timeoffset);
if (dob->type != OB_DUPLIGROUP) {
obd->flag |= OB_DONE;
@@ -5138,14 +5073,11 @@ static void database_init_objects(Render *re, unsigned int UNUSED(renderlay), in
}
}
else
- init_render_object(re, obd, ob, dob, dob_extra->obmat, timeoffset);
+ init_render_object(eval_ctx, re, obd, ob, dob, dob_extra->obmat, timeoffset);
if (re->test_break(re->tbh)) break;
}
- /* restore particle system */
- dupli_render_particle_set(re, ob, timeoffset, 0, false);
-
if (duplilist_apply_data) {
duplilist_restore(duplilist, duplilist_apply_data);
duplilist_free_apply_data(duplilist_apply_data);
@@ -5153,10 +5085,10 @@ static void database_init_objects(Render *re, unsigned int UNUSED(renderlay), in
free_object_duplilist(duplilist);
if (allow_render_object(re, ob, nolamps, onlyselected, actob))
- init_render_object(re, ob, NULL, NULL, NULL, timeoffset);
+ init_render_object(eval_ctx, re, ob, NULL, NULL, NULL, timeoffset);
}
else if (allow_render_object(re, ob, nolamps, onlyselected, actob))
- init_render_object(re, ob, NULL, NULL, NULL, timeoffset);
+ init_render_object(eval_ctx, re, ob, NULL, NULL, NULL, timeoffset);
}
if (re->test_break(re->tbh)) break;
@@ -5165,12 +5097,39 @@ static void database_init_objects(Render *re, unsigned int UNUSED(renderlay), in
/* objects in groups with OB_RENDER_DUPLI set still need to be created,
* since they may not be part of the scene */
for (group= re->main->group.first; group; group=group->id.next)
- add_group_render_dupli_obs(re, group, nolamps, onlyselected, actob, timeoffset, 0);
+ add_group_render_dupli_obs(eval_ctx, re, group, nolamps, onlyselected, actob, timeoffset, 0);
if (!re->test_break(re->tbh))
RE_makeRenderInstances(re);
}
+void RE_Database_CameraOnly(Render *re, Main *bmain, Scene *scene, unsigned int lay, int use_camera_view)
+{
+ Object *camera;
+ float mat[4][4];
+
+ re->main= bmain;
+ re->scene= scene;
+ re->lay= lay;
+
+ /* scene needs to be set to get camera */
+ camera= RE_GetCamera(re);
+
+ /* if no camera, viewmat should have been set! */
+ if (use_camera_view && camera) {
+ /* called before but need to call again in case of lens animation from the
+ * above call to BKE_scene_graph_update_for_newframe, fixes bug. [#22702].
+ * following calls don't depend on 'RE_SetCamera' */
+ RE_SetCamera(re, camera);
+ RE_GetCameraModelMatrix(re, camera, mat);
+ invert_m4(mat);
+ RE_SetView(re, mat);
+
+ /* force correct matrix for scaled cameras */
+ DEG_id_tag_update_ex(re->main, &camera->id, OB_RECALC_OB);
+ }
+}
+
/* used to be 'rotate scene' */
void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int lay, int use_camera_view)
{
@@ -5209,7 +5168,6 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
/* applies changes fully */
if ((re->r.scemode & (R_NO_FRAME_UPDATE|R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))==0) {
- BKE_scene_graph_update_for_newframe(re->eval_ctx, re->depsgraph, re->main, re->scene, NULL);
render_update_anim_renderdata(re, &re->scene->r, &re->scene->view_layers);
}
@@ -5246,7 +5204,12 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
set_node_shader_lamp_loop(shade_material_loop);
/* MAKE RENDER DATA */
- database_init_objects(re, lay, 0, 0, NULL, 0);
+ EvaluationContext *eval_ctx = NULL;
+ BLI_assert(eval_ctx);
+ /* This will break things, and it should because honestly this function is deprecated and no one uses it.
+ * maybe freestyle? But even so, this need to change. Even freestyle need to get data from depsgraph
+ * so we can't create the database only once. */
+ database_init_objects(eval_ctx, re, lay, 0, 0, NULL, 0);
if (!re->test_break(re->tbh)) {
set_material_lightgroups(re);
@@ -5261,7 +5224,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
}
}
-void RE_Database_Preprocess(Render *re)
+void RE_Database_Preprocess(EvaluationContext *eval_ctx, Render *re)
{
if (!re->test_break(re->tbh)) {
int tothalo;
@@ -5291,7 +5254,7 @@ void RE_Database_Preprocess(Render *re)
/* point density texture */
if (!re->test_break(re->tbh))
- make_pointdensities(re);
+ make_pointdensities(eval_ctx, re);
/* voxel data texture */
if (!re->test_break(re->tbh))
make_voxeldata(re);
@@ -5362,7 +5325,11 @@ void RE_DataBase_GetView(Render *re, float mat[4][4])
/* Speed Vectors */
/* ------------------------------------------------------------------------- */
-static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int lay, int timeoffset)
+static void database_fromscene_vectors(EvaluationContext *eval_ctx,
+ Render *re,
+ Scene *scene,
+ unsigned int lay,
+ int timeoffset)
{
Object *camera= RE_GetCamera(re);
float mat[4][4];
@@ -5379,7 +5346,7 @@ static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int la
/* applies changes fully */
scene->r.cfra += timeoffset;
- BKE_scene_graph_update_for_newframe(re->eval_ctx, re->depsgraph, re->main, re->scene, NULL);
+ BKE_scene_graph_update_for_newframe(eval_ctx->depsgraph, re->main);
/* if no camera, viewmat should have been set! */
if (camera) {
@@ -5390,7 +5357,7 @@ static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int la
}
/* MAKE RENDER DATA */
- database_init_objects(re, lay, 0, 0, NULL, timeoffset);
+ database_init_objects(eval_ctx, re, lay, 0, 0, NULL, timeoffset);
if (!re->test_break(re->tbh))
project_renderdata(re, projectverto, (re->r.mode & R_PANORAMA) != 0, 0, 1);
@@ -5747,7 +5714,7 @@ static void free_dbase_object_vectors(ListBase *lb)
BLI_freelistN(lb);
}
-void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned int lay)
+void RE_Database_FromScene_Vectors(EvaluationContext *eval_ctx, Render *re, Main *bmain, Scene *sce, unsigned int lay)
{
ObjectInstanceRen *obi, *oldobi;
StrandSurface *mesh;
@@ -5762,7 +5729,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned
speedvector_project(re, NULL, NULL, NULL); /* initializes projection code */
/* creates entire dbase */
- database_fromscene_vectors(re, sce, lay, -1);
+ database_fromscene_vectors(eval_ctx, re, sce, lay, -1);
/* copy away vertex info */
copy_dbase_object_vectors(re, &oldtable);
@@ -5778,7 +5745,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned
/* creates entire dbase */
re->i.infostr = IFACE_("Calculating next frame vectors");
- database_fromscene_vectors(re, sce, lay, +1);
+ database_fromscene_vectors(eval_ctx, re, sce, lay, +1);
}
/* copy away vertex info */
copy_dbase_object_vectors(re, &newtable);
@@ -5792,7 +5759,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned
if (!re->test_break(re->tbh)) {
RE_Database_FromScene(re, bmain, sce, lay, 1);
- RE_Database_Preprocess(re);
+ RE_Database_Preprocess(eval_ctx, re);
}
if (!re->test_break(re->tbh)) {
@@ -5886,7 +5853,8 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned
* RE_BAKE_DERIVATIVE:for baking, no lamps, only selected objects
* RE_BAKE_SHADOW: for baking, only shadows, but all objects
*/
-void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay, const int type, Object *actob)
+void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, ViewLayer *view_layer,
+ unsigned int lay, const int type, Object *actob)
{
Object *camera;
float mat[4][4];
@@ -5903,6 +5871,12 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
render_copy_viewrender(&re->view_render, &scene->view_render);
RE_init_threadcount(re);
+
+ EvaluationContext *eval_ctx = DEG_evaluation_context_new(DAG_EVAL_RENDER);
+ Depsgraph *depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
+ DEG_evaluation_context_init_from_view_layer_for_render(eval_ctx, depsgraph, scene, view_layer);
+ DEG_graph_build_from_view_layer(depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
re->flag |= R_BAKING;
re->excludeob= actob;
@@ -5974,7 +5948,7 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
set_node_shader_lamp_loop(shade_material_loop);
/* MAKE RENDER DATA */
- database_init_objects(re, lay, nolamps, onlyselected, actob, 0);
+ database_init_objects(eval_ctx, re, lay, nolamps, onlyselected, actob, 0);
set_material_lightgroups(re);
@@ -5990,7 +5964,7 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
/* point density texture */
if (!re->test_break(re->tbh))
- make_pointdensities(re);
+ make_pointdensities(eval_ctx, re);
/* voxel data texture */
if (!re->test_break(re->tbh))
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
index 2a7aab58980..19635dd26f2 100644
--- a/source/blender/render/intern/source/envmap.c
+++ b/source/blender/render/intern/source/envmap.c
@@ -71,7 +71,7 @@ static void envmap_split_ima(EnvMap *env, ImBuf *ibuf)
int dx, part;
/* after lock we test cube[1], if set the other thread has done it fine */
- BLI_lock_thread(LOCK_IMAGE);
+ BLI_thread_lock(LOCK_IMAGE);
if (env->cube[1] == NULL) {
BKE_texture_envmap_free_data(env);
@@ -119,7 +119,7 @@ static void envmap_split_ima(EnvMap *env, ImBuf *ibuf)
}
}
}
- BLI_unlock_thread(LOCK_IMAGE);
+ BLI_thread_unlock(LOCK_IMAGE);
}
/* ------------------------------------------------------------------------- */
@@ -250,12 +250,12 @@ static void env_set_imats(Render *re)
{
float mat[4][4];
- FOREACH_SCENE_OBJECT(re->scene, ob)
+ FOREACH_SCENE_OBJECT_BEGIN(re->scene, ob)
{
mul_m4_m4m4(mat, re->viewmat, ob->obmat);
invert_m4_m4(ob->imat, mat);
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
}
/* ------------------------------------------------------------------------- */
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 68077d4d93b..245a49ad5ae 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -1,11 +1,10 @@
/*
-
* ***** 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.
+ * 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
@@ -42,6 +41,8 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "DNA_object_types.h"
+
#include "BKE_camera.h"
#include "BKE_global.h"
#include "BKE_colortools.h"
@@ -50,6 +51,7 @@
#include "BKE_scene.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "RNA_access.h"
@@ -155,6 +157,13 @@ bool RE_engine_is_external(Render *re)
return (re->engine && re->engine->type && re->engine->type->render_to_image);
}
+bool RE_engine_is_opengl(RenderEngineType *render_type)
+{
+ /* TODO refine? Can we have ogl render engine without ogl render pipeline? */
+ return (render_type->draw_engine != NULL) &&
+ DRW_engine_render_support(render_type->draw_engine);
+}
+
/* Create, Free */
RenderEngine *RE_engine_create(RenderEngineType *type)
@@ -170,7 +179,7 @@ RenderEngine *RE_engine_create_ex(RenderEngineType *type, bool use_for_viewport)
if (use_for_viewport) {
engine->flag |= RE_ENGINE_USED_FOR_VIEWPORT;
- BLI_begin_threaded_malloc();
+ BLI_threaded_malloc_begin();
}
return engine;
@@ -185,7 +194,7 @@ void RE_engine_free(RenderEngine *engine)
#endif
if (engine->flag & RE_ENGINE_USED_FOR_VIEWPORT) {
- BLI_end_threaded_malloc();
+ BLI_threaded_malloc_end();
}
MEM_freeN(engine);
@@ -518,10 +527,51 @@ RenderData *RE_engine_get_render_data(Render *re)
return &re->r;
}
+/* Depsgraph */
+static void engine_depsgraph_init(RenderEngine *engine, ViewLayer *view_layer)
+{
+ Main *bmain = engine->re->main;
+ Scene *scene = engine->re->scene;
+
+ engine->depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
+
+ BKE_scene_graph_update_tagged(engine->depsgraph, bmain);
+}
+
+static void engine_depsgraph_free(RenderEngine *engine)
+{
+ DEG_graph_free(engine->depsgraph);
+
+ engine->depsgraph = NULL;
+}
+
+void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe)
+{
+ if(!engine->depsgraph) {
+ return;
+ }
+
+ Render *re = engine->re;
+ double cfra = (double)frame + (double)subframe;
+
+ CLAMP(cfra, MINAFRAME, MAXFRAME);
+ BKE_scene_frame_set(re->scene, cfra);
+ BKE_scene_graph_update_for_newframe(engine->depsgraph, re->main);
+
+#ifdef WITH_PYTHON
+ BPy_BEGIN_ALLOW_THREADS;
+#endif
+
+#ifdef WITH_PYTHON
+ BPy_END_ALLOW_THREADS;
+#endif
+
+ BKE_scene_camera_switch_update(re->scene);
+}
+
/* Bake */
-void RE_bake_engine_set_engine_parameters(Render *re, Main *bmain, Depsgraph *graph, Scene *scene)
+void RE_bake_engine_set_engine_parameters(Render *re, Main *bmain, Scene *scene)
{
- re->depsgraph = graph;
re->scene = scene;
re->main = bmain;
render_copy_renderdata(&re->r, &scene->r);
@@ -572,20 +622,25 @@ bool RE_bake_engine(
/* update is only called so we create the engine.session */
if (type->update)
- type->update(engine, re->main, re->depsgraph, re->scene);
+ type->update(engine, re->main, re->scene);
if (type->bake) {
- type->bake(
- engine,
- re->scene,
- object,
- pass_type,
- pass_filter,
- object_id,
- pixel_array,
- num_pixels,
- depth,
- result);
+ ViewLayer *view_layer = BLI_findlink(&re->scene->view_layers, re->scene->active_view_layer);
+ engine_depsgraph_init(engine, view_layer);
+
+ type->bake(engine,
+ engine->depsgraph,
+ re->scene,
+ object,
+ pass_type,
+ pass_filter,
+ object_id,
+ pixel_array,
+ num_pixels,
+ depth,
+ result);
+
+ engine_depsgraph_free(engine);
}
engine->tile_x = 0;
@@ -609,28 +664,6 @@ bool RE_bake_engine(
return true;
}
-void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe)
-{
- Render *re = engine->re;
- Scene *scene = re->scene;
- double cfra = (double)frame + (double)subframe;
-
- CLAMP(cfra, MINAFRAME, MAXFRAME);
- BKE_scene_frame_set(scene, cfra);
-
-#ifdef WITH_PYTHON
- BPy_BEGIN_ALLOW_THREADS;
-#endif
-
- BKE_scene_graph_update_for_newframe(re->eval_ctx, re->depsgraph, re->main, scene, NULL);
-
-#ifdef WITH_PYTHON
- BPy_END_ALLOW_THREADS;
-#endif
-
- BKE_scene_camera_switch_update(scene);
-}
-
/* Render */
int RE_engine_render(Render *re, int do_all)
@@ -657,7 +690,6 @@ int RE_engine_render(Render *re, int do_all)
/* update animation here so any render layer animation is applied before
* creating the render result */
if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) {
- BKE_scene_graph_update_for_newframe(re->eval_ctx, re->depsgraph, re->main, re->scene, NULL);
render_update_anim_renderdata(re, &re->scene->r, &re->scene->view_layers);
}
@@ -724,7 +756,7 @@ int RE_engine_render(Render *re, int do_all)
render_result_exr_file_begin(re);
if (type->update) {
- type->update(engine, re->main, re->depsgraph, re->scene);
+ type->update(engine, re->main, re->scene);
}
/* Clear UI drawing locks. */
@@ -733,7 +765,16 @@ int RE_engine_render(Render *re, int do_all)
}
if (type->render_to_image) {
- type->render_to_image(engine, re->depsgraph);
+ FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re, view_layer_iter)
+ {
+ ViewLayer *view_layer = BLI_findstring(&re->scene->view_layers, view_layer_iter->name, offsetof(ViewLayer, name));
+ engine_depsgraph_init(engine, view_layer);
+
+ type->render_to_image(engine, engine->depsgraph);
+
+ engine_depsgraph_free(engine);
+ }
+ FOREACH_VIEW_LAYER_TO_RENDER_END;
}
engine->tile_x = 0;
@@ -796,8 +837,3 @@ void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, s
}
}
}
-
-ViewLayer *RE_engine_get_view_layer(Render *re)
-{
- return re->eval_ctx->view_layer;
-}
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index ae02cf56b88..6e5d10fcc84 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -890,18 +890,18 @@ static void image_mipmap_test(Tex *tex, ImBuf *ibuf)
if ((ibuf->flags & IB_fields) == 0) {
if (ibuf->mipmap[0] && (ibuf->userflags & IB_MIPMAP_INVALID)) {
- BLI_lock_thread(LOCK_IMAGE);
+ BLI_thread_lock(LOCK_IMAGE);
if (ibuf->userflags & IB_MIPMAP_INVALID) {
IMB_remakemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
ibuf->userflags &= ~IB_MIPMAP_INVALID;
}
- BLI_unlock_thread(LOCK_IMAGE);
+ BLI_thread_unlock(LOCK_IMAGE);
}
if (ibuf->mipmap[0] == NULL) {
- BLI_lock_thread(LOCK_IMAGE);
+ BLI_thread_lock(LOCK_IMAGE);
if (ibuf->mipmap[0] == NULL)
IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
- BLI_unlock_thread(LOCK_IMAGE);
+ BLI_thread_unlock(LOCK_IMAGE);
}
/* if no mipmap could be made, fall back on non-mipmap render */
if (ibuf->mipmap[0] == NULL) {
diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c
index 731a5ec4e22..13c95dac05d 100644
--- a/source/blender/render/intern/source/initrender.c
+++ b/source/blender/render/intern/source/initrender.c
@@ -38,7 +38,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLI_jitter.h"
+#include "BLI_jitter_2d.h"
#include "BLI_utildefines.h"
#include "DNA_camera_types.h"
@@ -501,11 +501,6 @@ void RE_SetCamera(Render *re, Object *cam_ob)
re_camera_params_get(re, &params, cam_ob);
}
-void RE_SetDepsgraph(Render *re, Depsgraph *graph)
-{
- re->depsgraph = graph;
-}
-
void RE_SetPixelSize(Render *re, float pixsize)
{
re->viewdx = pixsize;
diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c
index 4c0355ef604..ddab8b23b59 100644
--- a/source/blender/render/intern/source/multires_bake.c
+++ b/source/blender/render/intern/source/multires_bake.c
@@ -470,7 +470,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t
bake_data = initBakeData(bkr, ima);
if (tot_thread > 1)
- BLI_init_threads(&threads, do_multires_bake_thread, tot_thread);
+ BLI_threadpool_init(&threads, do_multires_bake_thread, tot_thread);
handles = MEM_callocN(tot_thread * sizeof(MultiresBakeThread), "do_multires_bake handles");
@@ -512,12 +512,12 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t
init_bake_rast(&handle->bake_rast, ibuf, &handle->data, flush_pixel, bkr->do_update);
if (tot_thread > 1)
- BLI_insert_thread(&threads, handle);
+ BLI_threadpool_insert(&threads, handle);
}
/* run threads */
if (tot_thread > 1)
- BLI_end_threads(&threads);
+ BLI_threadpool_end(&threads);
else
do_multires_bake_thread(&handles[0]);
diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c
index cd93898d846..42200a8278c 100644
--- a/source/blender/render/intern/source/occlusion.c
+++ b/source/blender/render/intern/source/occlusion.c
@@ -553,7 +553,7 @@ static void occ_build_recursive(OcclusionTree *tree, OccNode *node, int begin, i
occ_build_8_split(tree, begin, end, offset, count);
if (depth == 1 && tree->dothreadedbuild)
- BLI_init_threads(&threads, exec_occ_build, tree->totbuildthread);
+ BLI_threadpool_init(&threads, exec_occ_build, tree->totbuildthread);
for (b = 0; b < TOTCHILD; b++) {
if (count[b] == 0) {
@@ -566,7 +566,7 @@ static void occ_build_recursive(OcclusionTree *tree, OccNode *node, int begin, i
}
else {
if (tree->dothreadedbuild)
- BLI_lock_thread(LOCK_CUSTOM1);
+ BLI_thread_lock(LOCK_CUSTOM1);
child = BLI_memarena_alloc(tree->arena, sizeof(OccNode));
node->child[b].node = child;
@@ -576,7 +576,7 @@ static void occ_build_recursive(OcclusionTree *tree, OccNode *node, int begin, i
tree->maxdepth = depth + 1;
if (tree->dothreadedbuild)
- BLI_unlock_thread(LOCK_CUSTOM1);
+ BLI_thread_unlock(LOCK_CUSTOM1);
if (depth == 1 && tree->dothreadedbuild) {
othreads[totthread].tree = tree;
@@ -584,7 +584,7 @@ static void occ_build_recursive(OcclusionTree *tree, OccNode *node, int begin, i
othreads[totthread].begin = offset[b];
othreads[totthread].end = offset[b] + count[b];
othreads[totthread].depth = depth + 1;
- BLI_insert_thread(&threads, &othreads[totthread]);
+ BLI_threadpool_insert(&threads, &othreads[totthread]);
totthread++;
}
else
@@ -593,7 +593,7 @@ static void occ_build_recursive(OcclusionTree *tree, OccNode *node, int begin, i
}
if (depth == 1 && tree->dothreadedbuild)
- BLI_end_threads(&threads);
+ BLI_threadpool_end(&threads);
}
/* combine area, position and sh */
@@ -1313,12 +1313,12 @@ void make_occ_tree(Render *re)
exec_strandsurface_sample(&othreads[0]);
}
else {
- BLI_init_threads(&threads, exec_strandsurface_sample, totthread);
+ BLI_threadpool_init(&threads, exec_strandsurface_sample, totthread);
for (a = 0; a < totthread; a++)
- BLI_insert_thread(&threads, &othreads[a]);
+ BLI_threadpool_insert(&threads, &othreads[a]);
- BLI_end_threads(&threads);
+ BLI_threadpool_end(&threads);
}
for (a = 0; a < mesh->totface; a++) {
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 5a5c99724fe..9ad9c653e54 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -41,6 +41,7 @@
#include "DNA_image_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_userdef_types.h"
@@ -80,11 +81,14 @@
#include "BKE_object.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#include "PIL_time.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "IMB_metadata.h"
#include "RE_engine.h"
#include "RE_pipeline.h"
@@ -258,6 +262,11 @@ RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name)
}
}
+bool RE_HasSingleLayer(Render *re)
+{
+ return (re->r.scemode & R_SINGLE_LAYER);
+}
+
RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty)
{
return render_result_new_from_exr(exrhandle, colorspace, predivide, rectx, recty);
@@ -265,15 +274,22 @@ RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, bool
RenderLayer *render_get_active_layer(Render *re, RenderResult *rr)
{
- RenderLayer *rl = BLI_findlink(&rr->layers, re->active_view_layer);
-
- if (rl)
- return rl;
- else
- return rr->layers.first;
+ ViewLayer *view_layer = BLI_findlink(&re->view_layers, re->active_view_layer);
+
+ if (view_layer) {
+ RenderLayer *rl = BLI_findstring(&rr->layers,
+ view_layer->name,
+ offsetof(RenderLayer, name));
+
+ if (rl) {
+ return rl;
+ }
+ }
+
+ return rr->layers.first;
}
-static int render_scene_needs_vector(Render *re)
+static int UNUSED_FUNCTION(render_scene_needs_vector)(Render *re)
{
ViewLayer *view_layer;
for (view_layer = re->view_layers.first; view_layer; view_layer = view_layer->next)
@@ -354,15 +370,6 @@ Scene *RE_GetScene(Render *re)
return NULL;
}
-EvaluationContext *RE_GetEvalCtx(Render *re)
-{
- if (re) {
- return re->eval_ctx;
- }
-
- return NULL;
-}
-
/**
* Same as #RE_AcquireResultImage but creating the necessary views to store the result
* fill provided result struct with a copy of thew views of what is done so far the
@@ -514,7 +521,6 @@ Render *RE_NewRender(const char *name)
BLI_strncpy(re->name, name, RE_MAXNAME);
BLI_rw_mutex_init(&re->resultmutex);
BLI_rw_mutex_init(&re->partsmutex);
- re->eval_ctx = DEG_evaluation_context_new(DAG_EVAL_RENDER);
}
RE_InitRenderCB(re);
@@ -591,7 +597,6 @@ void RE_FreeRender(Render *re)
/* main dbase can already be invalid now, some database-free code checks it */
re->main = NULL;
re->scene = NULL;
- re->depsgraph = NULL;
RE_Database_Free(re); /* view render can still have full database */
free_sample_tables(re);
@@ -600,7 +605,6 @@ void RE_FreeRender(Render *re)
render_result_free(re->pushedresult);
BLI_remlink(&RenderGlobal.renderlist, re);
- MEM_freeN(re->eval_ctx);
MEM_freeN(re);
}
@@ -861,12 +865,11 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
re->result->recty = re->recty;
render_result_view_new(re->result, "");
}
-
- if (re->r.scemode & R_VIEWPORT_PREVIEW)
- re->eval_ctx->mode = DAG_EVAL_PREVIEW;
- else
- re->eval_ctx->mode = DAG_EVAL_RENDER;
-
+
+ eEvaluationMode mode = (re->r.scemode & R_VIEWPORT_PREVIEW) ? DAG_EVAL_PREVIEW : DAG_EVAL_RENDER;
+ /* If we had a consistent EvaluationContext now would be the time to update it. */
+ (void)mode;
+
/* ensure renderdatabase can use part settings correct */
RE_parts_clamp(re);
@@ -1352,7 +1355,7 @@ static void *do_render_thread(void *thread_v)
return NULL;
}
-static void main_render_result_end(Render *re)
+static void UNUSED_FUNCTION(main_render_result_end)(Render *re)
{
if (re->result->do_exr_tile) {
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
@@ -1427,7 +1430,7 @@ static void threaded_tile_processor(Render *re)
BLI_thread_queue_nowait(workqueue);
/* start all threads */
- BLI_init_threads(&threads, do_render_thread, re->r.threads);
+ BLI_threadpool_init(&threads, do_render_thread, re->r.threads);
for (a = 0; a < re->r.threads; a++) {
thread[a].workqueue = workqueue;
@@ -1443,7 +1446,7 @@ static void threaded_tile_processor(Render *re)
thread[a].duh = NULL;
}
- BLI_insert_thread(&threads, &thread[a]);
+ BLI_threadpool_insert(&threads, &thread[a]);
}
/* wait for results to come back */
@@ -1487,7 +1490,7 @@ static void threaded_tile_processor(Render *re)
}
}
- BLI_end_threads(&threads);
+ BLI_threadpool_end(&threads);
if ((g_break=re->test_break(re->tbh)))
break;
@@ -1558,81 +1561,10 @@ void RE_TileProcessor(Render *re)
static void do_render_3d(Render *re)
{
- RenderView *rv;
-
re->current_scene_update(re->suh, re->scene);
- /* try external */
- if (RE_engine_render(re, 0))
- return;
-
- /* internal */
- RE_parts_clamp(re);
-
- /* add motion blur and fields offset to frames */
- const int cfra_backup = re->scene->r.cfra;
- const float subframe_backup = re->scene->r.subframe;
-
- BKE_scene_frame_set(
- re->scene, (double)re->scene->r.cfra + (double)re->scene->r.subframe +
- (double)re->mblur_offs + (double)re->field_offs);
-
- /* init main render result */
- main_render_result_new(re);
- if (re->result == NULL) {
- BKE_report(re->reports, RPT_ERROR, "Failed allocate render result, out of memory");
- G.is_break = true;
- return;
- }
-
-#ifdef WITH_FREESTYLE
- if (re->r.mode & R_EDGE_FRS) {
- init_freestyle(re);
- }
-#endif
-
- /* we need a new database for each view */
- for (rv = re->result->views.first; rv; rv = rv->next) {
- RE_SetActiveRenderView(re, rv->name);
-
- /* lock drawing in UI during data phase */
- if (re->draw_lock)
- re->draw_lock(re->dlh, 1);
-
- /* make render verts/faces/halos/lamps */
- if (render_scene_needs_vector(re))
- RE_Database_FromScene_Vectors(re, re->main, re->scene, re->lay);
- else {
- RE_Database_FromScene(re, re->main, re->scene, re->lay, 1);
- RE_Database_Preprocess(re);
- }
-
- /* clear UI drawing locks */
- if (re->draw_lock)
- re->draw_lock(re->dlh, 0);
-
- threaded_tile_processor(re);
-
-#ifdef WITH_FREESTYLE
- /* Freestyle */
- if (re->r.mode & R_EDGE_FRS)
- if (!re->test_break(re->tbh))
- add_freestyle(re, 1);
-#endif
-
- /* do left-over 3d post effects (flares) */
- if (re->flag & R_HALO)
- if (!re->test_break(re->tbh))
- add_halo_flare(re);
-
- /* free all render verts etc */
- RE_Database_Free(re);
- }
-
- main_render_result_end(re);
-
- re->scene->r.cfra = cfra_backup;
- re->scene->r.subframe = subframe_backup;
+ /* All the rendering pipeline goes through "external" render engines. */
+ RE_engine_render(re, 0);
}
/* called by blur loop, accumulate RGBA key alpha */
@@ -1747,11 +1679,6 @@ static void do_render_blur_3d(Render *re)
re->mblur_offs = 0.0f;
re->i.curblur = 0; /* stats */
- /* make sure motion blur changes get reset to current frame */
- if ((re->r.scemode & (R_NO_FRAME_UPDATE|R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))==0) {
- BKE_scene_graph_update_for_newframe(re->eval_ctx, re->depsgraph, re->main, re->scene, NULL);
- }
-
/* weak... the display callback wants an active renderlayer pointer... */
re->result->renlay = render_get_active_layer(re, re->result);
re->display_update(re->duh, re->result, NULL);
@@ -1985,7 +1912,6 @@ static void render_scene(Render *re, Scene *sce, int cfra)
/* still unsure entity this... */
resc->main = re->main;
- resc->depsgraph = re->depsgraph;
resc->scene = sce;
resc->lay = sce->lay;
resc->scene_color_manage = BKE_scene_check_color_management_enabled(sce);
@@ -2068,7 +1994,7 @@ bool RE_allow_render_generic_object(Object *ob)
#ifdef DEPSGRAPH_WORKAROUND_HACK
static void tag_dependend_objects_for_render(Scene *scene, int UNUSED(renderlay))
{
- FOREACH_OBJECT_RENDERABLE(scene, object)
+ FOREACH_OBJECT_RENDERABLE_BEGIN(scene, object)
{
if (object->type == OB_MESH) {
if (RE_allow_render_generic_object(object)) {
@@ -2104,11 +2030,33 @@ static void tag_dependend_objects_for_render(Scene *scene, int UNUSED(renderlay)
DEG_id_tag_update(&smd->target->id, OB_RECALC_DATA);
}
}
+ else if (md->type == eModifierType_ParticleSystem) {
+ ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
+ ParticleSystem *psys = psmd->psys;
+ ParticleSettings *part = psys->part;
+ switch (part->ren_as) {
+ case PART_DRAW_OB:
+ if (part->dup_ob != NULL) {
+ DEG_id_tag_update(&part->dup_ob->id, OB_RECALC_DATA);
+ }
+ break;
+ case PART_DRAW_GR:
+ if (part->dup_group != NULL) {
+ for (GroupObject *go = part->dup_group->gobject.first;
+ go != NULL;
+ go = go->next)
+ {
+ DEG_id_tag_update(&go->ob->id, OB_RECALC_DATA);
+ }
+ }
+ break;
+ }
+ }
}
}
}
}
- FOREACH_OBJECT_RENDERABLE_END
+ FOREACH_OBJECT_RENDERABLE_END;
}
#endif
@@ -2673,8 +2621,9 @@ static void do_render_composite_fields_blur_3d(Render *re)
R.i.starttime = re->i.starttime;
R.i.cfra = re->i.cfra;
- if (update_newframe)
- BKE_scene_graph_update_for_newframe(re->eval_ctx, re->depsgraph, re->main, re->scene, NULL);
+ if (update_newframe) {
+ /* If we have consistent depsgraph now would be a time to update them. */
+ }
if (re->r.scemode & R_FULL_SAMPLE)
do_merge_fullsample(re, ntree);
@@ -2784,9 +2733,10 @@ static void do_render_seq(Render *re)
tot_views = BKE_scene_multiview_num_views_get(&re->r);
ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * tot_views, "Sequencer Views ImBufs");
+ EvaluationContext *eval_ctx = DEG_evaluation_context_new(DAG_EVAL_RENDER);
BKE_sequencer_new_render_data(
- re->eval_ctx, re->main, re->scene,
+ eval_ctx, re->main, re->scene,
re_x, re_y, 100,
&context);
@@ -2808,6 +2758,8 @@ static void do_render_seq(Render *re)
}
}
+ DEG_evaluation_context_free(eval_ctx);
+
rr = re->result;
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
@@ -3375,10 +3327,8 @@ void RE_RenderFreestyleExternal(Render *re)
for (rv = re->result->views.first; rv; rv = rv->next) {
RE_SetActiveRenderView(re, rv->name);
- RE_Database_FromScene(re, re->main, re->scene, re->lay, 1);
- RE_Database_Preprocess(re);
+ RE_Database_CameraOnly(re, re->main, re->scene, re->lay, 1);
add_freestyle(re, 1);
- RE_Database_Free(re);
}
}
}
@@ -3392,7 +3342,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen
if (!rr)
return false;
- bool is_mono = BLI_listbase_count_ex(&rr->views, 2) < 2;
+ bool is_mono = BLI_listbase_count_at_most(&rr->views, 2) < 2;
bool is_exr_rr = ELEM(rd->im_format.imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER) &&
RE_HasFloatPixels(rr);
@@ -3509,7 +3459,7 @@ bool RE_WriteRenderViewsMovie(
if (!rr)
return false;
- is_mono = BLI_listbase_count_ex(&rr->views, 2) < 2;
+ is_mono = BLI_listbase_count_at_most(&rr->views, 2) < 2;
if (is_mono || (scene->r.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)) {
int view_id;
@@ -3749,8 +3699,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
NULL, camera_override, lay_override, 1, 0);
if (nfra != scene->r.cfra) {
- /* Skip this frame, but update for physics and particles system. */
- BKE_scene_graph_update_for_newframe(re->eval_ctx, re->depsgraph, bmain, scene, NULL);
+ /* Skip this frame, but could update for physics and particles system. */
continue;
}
else
@@ -3899,7 +3848,6 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
void RE_PreviewRender(Render *re, Main *bmain, Scene *sce, ViewRender *view_render)
{
Object *camera;
- ViewLayer *view_layer = BKE_view_layer_from_scene_get(sce);
int winx, winy;
winx = (sce->r.size * sce->r.xsch) / 100;
@@ -3913,8 +3861,6 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce, ViewRender *view_rend
re->scene = sce;
re->scene_color_manage = BKE_scene_check_color_management_enabled(sce);
re->lay = sce->lay;
- re->depsgraph = BKE_scene_get_depsgraph(sce, view_layer, false);
- re->eval_ctx->view_layer = view_layer;
camera = RE_GetCamera(re);
RE_SetCamera(re, camera);
@@ -4103,7 +4049,7 @@ bool RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env,
/* Used in the interface to decide whether to show layers or passes. */
bool RE_layers_have_name(struct RenderResult *rr)
{
- switch (BLI_listbase_count_ex(&rr->layers, 2)) {
+ switch (BLI_listbase_count_at_most(&rr->layers, 2)) {
case 0:
return false;
case 1:
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index 4f300b7286c..bba422345e0 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -59,6 +59,7 @@
#include "BKE_colortools.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "render_types.h"
#include "texture.h"
@@ -169,13 +170,10 @@ static void alloc_point_data(PointDensity *pd)
}
}
-static void pointdensity_cache_psys(EvaluationContext *eval_ctx, Scene *scene,
+static void pointdensity_cache_psys(const EvaluationContext *eval_ctx, Scene *scene,
PointDensity *pd,
Object *ob,
ParticleSystem *psys,
- float viewmat[4][4],
- float winmat[4][4],
- int winx, int winy,
const bool use_render_params)
{
DerivedMesh *dm;
@@ -197,11 +195,6 @@ static void pointdensity_cache_psys(EvaluationContext *eval_ctx, Scene *scene,
data_used = point_data_used(pd);
- /* Just to create a valid rendering context for particles */
- if (use_render_params) {
- psys_render_set(ob, psys, viewmat, winmat, winx, winy, 0);
- }
-
if (use_render_params) {
dm = mesh_create_derived_render(eval_ctx, scene,
ob,
@@ -214,7 +207,6 @@ static void pointdensity_cache_psys(EvaluationContext *eval_ctx, Scene *scene,
}
if (!psys_check_enabled(ob, psys, use_render_params)) {
- psys_render_restore(ob, psys);
return;
}
@@ -307,10 +299,6 @@ static void pointdensity_cache_psys(EvaluationContext *eval_ctx, Scene *scene,
end_latt_deform(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
}
-
- if (use_render_params) {
- psys_render_restore(ob, psys);
- }
}
@@ -403,7 +391,7 @@ static void pointdensity_cache_vertex_normal(PointDensity *pd, Object *UNUSED(ob
}
}
-static void pointdensity_cache_object(EvaluationContext *eval_ctx, Scene *scene,
+static void pointdensity_cache_object(const EvaluationContext *eval_ctx, Scene *scene,
PointDensity *pd,
Object *ob,
const bool use_render_params)
@@ -478,11 +466,9 @@ static void pointdensity_cache_object(EvaluationContext *eval_ctx, Scene *scene,
}
-static void cache_pointdensity_ex(EvaluationContext *eval_ctx, Scene *scene,
+static void cache_pointdensity_ex(const EvaluationContext *eval_ctx,
+ Scene *scene,
PointDensity *pd,
- float viewmat[4][4],
- float winmat[4][4],
- int winx, int winy,
const bool use_render_params)
{
if (pd == NULL) {
@@ -512,8 +498,6 @@ static void cache_pointdensity_ex(EvaluationContext *eval_ctx, Scene *scene,
pd,
ob,
psys,
- viewmat, winmat,
- winx, winy,
use_render_params);
}
else if (pd->source == TEX_PD_OBJECT) {
@@ -523,13 +507,11 @@ static void cache_pointdensity_ex(EvaluationContext *eval_ctx, Scene *scene,
}
}
-void cache_pointdensity(Render *re, PointDensity *pd)
+void cache_pointdensity(const EvaluationContext *eval_ctx, Render *re, PointDensity *pd)
{
- cache_pointdensity_ex(re->eval_ctx,
+ cache_pointdensity_ex(eval_ctx,
re->scene,
pd,
- re->viewmat, re->winmat,
- re->winx, re->winy,
true);
}
@@ -551,7 +533,7 @@ void free_pointdensity(PointDensity *pd)
pd->totpoints = 0;
}
-void make_pointdensities(Render *re)
+void make_pointdensities(const EvaluationContext *eval_ctx, Render *re)
{
Tex *tex;
@@ -564,7 +546,7 @@ void make_pointdensities(Render *re)
for (tex = re->main->tex.first; tex != NULL; tex = tex->id.next) {
if (tex->id.us && tex->type == TEX_POINTDENSITY) {
- cache_pointdensity(re, tex->pd);
+ cache_pointdensity(eval_ctx, re, tex->pd);
}
}
@@ -881,12 +863,11 @@ static void sample_dummy_point_density(int resolution, float *values)
memset(values, 0, sizeof(float) * 4 * resolution * resolution * resolution);
}
-static void particle_system_minmax(EvaluationContext *eval_ctx,
+static void particle_system_minmax(const EvaluationContext *eval_ctx,
Scene *scene,
Object *object,
ParticleSystem *psys,
float radius,
- const bool use_render_params,
float min[3], float max[3])
{
const float size[3] = {radius, radius, radius};
@@ -905,9 +886,6 @@ static void particle_system_minmax(EvaluationContext *eval_ctx,
}
unit_m4(mat);
- if (use_render_params) {
- psys_render_set(object, psys, mat, mat, 1, 1, 0);
- }
sim.eval_ctx = eval_ctx;
sim.scene = scene;
@@ -937,40 +915,30 @@ static void particle_system_minmax(EvaluationContext *eval_ctx,
end_latt_deform(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
}
-
- if (use_render_params) {
- psys_render_restore(object, psys);
- }
}
void RE_point_density_cache(
- Scene *scene,
- ViewLayer *view_layer,
- PointDensity *pd,
- const bool use_render_params)
+ const struct EvaluationContext *eval_ctx,
+ PointDensity *pd)
{
- EvaluationContext eval_ctx = {0};
- float mat[4][4];
+ const bool use_render_params = (eval_ctx->mode == DAG_EVAL_RENDER);
- DEG_evaluation_context_init(&eval_ctx, use_render_params ? DAG_EVAL_RENDER
- : DAG_EVAL_VIEWPORT);
-
- eval_ctx.view_layer = view_layer;
+ Depsgraph *depsgraph = eval_ctx->depsgraph;
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
/* Same matricies/resolution as dupli_render_particle_set(). */
- unit_m4(mat);
BLI_mutex_lock(&sample_mutex);
- cache_pointdensity_ex(&eval_ctx, scene, pd, mat, mat, 1, 1, use_render_params);
+ cache_pointdensity_ex(eval_ctx, scene, pd, use_render_params);
BLI_mutex_unlock(&sample_mutex);
}
void RE_point_density_minmax(
- struct Scene *scene,
- ViewLayer *view_layer,
+ const struct EvaluationContext *eval_ctx,
struct PointDensity *pd,
- const bool use_render_params,
float r_min[3], float r_max[3])
{
+ Depsgraph *depsgraph = eval_ctx->depsgraph;
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
Object *object = pd->object;
if (object == NULL) {
zero_v3(r_min);
@@ -979,7 +947,6 @@ void RE_point_density_minmax(
}
if (pd->source == TEX_PD_PSYS) {
ParticleSystem *psys;
- EvaluationContext eval_ctx = {0};
if (pd->psys == 0) {
zero_v3(r_min);
@@ -993,18 +960,11 @@ void RE_point_density_minmax(
return;
}
- DEG_evaluation_context_init(&eval_ctx, use_render_params ? DAG_EVAL_RENDER :
- DAG_EVAL_VIEWPORT);
-
- eval_ctx.ctime = (float)scene->r.cfra + scene->r.subframe;
- eval_ctx.view_layer = view_layer;
-
- particle_system_minmax(&eval_ctx,
+ particle_system_minmax(eval_ctx,
scene,
object,
psys,
pd->radius,
- use_render_params,
r_min, r_max);
}
else {
@@ -1072,11 +1032,9 @@ static void point_density_sample_func(
* NOTE 2: Frees point density structure after sampling.
*/
void RE_point_density_sample(
- Scene *scene,
- ViewLayer *view_layer,
+ const EvaluationContext *eval_ctx,
PointDensity *pd,
const int resolution,
- const bool use_render_params,
float *values)
{
Object *object = pd->object;
@@ -1092,10 +1050,8 @@ void RE_point_density_sample(
}
BLI_mutex_lock(&sample_mutex);
- RE_point_density_minmax(scene,
- view_layer,
+ RE_point_density_minmax(eval_ctx,
pd,
- use_render_params,
min,
max);
BLI_mutex_unlock(&sample_mutex);
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index 6749fedb16e..5abef431f3d 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -266,9 +266,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
RenderResult *rr;
RenderLayer *rl;
RenderView *rv;
- ViewLayer *view_layer;
int rectx, recty;
- int nr;
rectx = BLI_rcti_size_x(partrct);
recty = BLI_rcti_size_y(partrct);
@@ -296,23 +294,14 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
render_result_views_new(rr, &re->r);
/* check renderdata for amount of layers */
- for (nr = 0, view_layer = re->view_layers.first; view_layer; view_layer = view_layer->next, nr++) {
-
- if (layername && layername[0])
- if (!STREQ(view_layer->name, layername))
- continue;
-
- if (re->r.scemode & R_SINGLE_LAYER) {
- if (nr != re->active_view_layer) {
- continue;
- }
- }
- else {
- if ((view_layer->flag & VIEW_LAYER_RENDER) == 0) {
+ FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re, view_layer)
+ {
+ if (layername && layername[0]) {
+ if (!STREQ(view_layer->name, layername)) {
continue;
}
}
-
+
rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
BLI_addtail(&rr->layers, rl);
@@ -417,6 +406,8 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
#undef RENDER_LAYER_ADD_PASS_SAFE
}
}
+ FOREACH_VIEW_LAYER_TO_RENDER_END;
+
/* sss, previewrender and envmap don't do layers, so we make a default one */
if (BLI_listbase_is_empty(&rr->layers) && !(layername && layername[0])) {
rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
@@ -749,7 +740,7 @@ void render_result_views_new(RenderResult *rr, RenderData *rd)
}
/* we always need at least one view */
- if (BLI_listbase_count_ex(&rr->views, 1) == 0) {
+ if (BLI_listbase_count_at_most(&rr->views, 1) == 0) {
render_result_view_new(rr, "");
}
}
@@ -1037,7 +1028,7 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, cons
RenderPass *rpassp;
int offs, partx, party;
- BLI_lock_thread(LOCK_IMAGE);
+ BLI_thread_lock(LOCK_IMAGE);
for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) {
rl = RE_GetRenderLayer(rr, rlp->name);
@@ -1086,7 +1077,7 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, cons
IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, viewname, false);
}
- BLI_unlock_thread(LOCK_IMAGE);
+ BLI_thread_unlock(LOCK_IMAGE);
}
void render_result_save_empty_result_tiles(Render *re)
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index 4241dff96de..cefa739a796 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -3675,7 +3675,7 @@ void render_realtime_texture(ShadeInput *shi, Image *ima)
if (R.r.scemode & R_NO_TEX) return;
if (firsttime) {
- BLI_lock_thread(LOCK_IMAGE);
+ BLI_thread_lock(LOCK_IMAGE);
if (firsttime) {
const int num_threads = BLI_system_thread_count();
for (a = 0; a < num_threads; a++) {
@@ -3686,7 +3686,7 @@ void render_realtime_texture(ShadeInput *shi, Image *ima)
firsttime= 0;
}
- BLI_unlock_thread(LOCK_IMAGE);
+ BLI_thread_unlock(LOCK_IMAGE);
}
tex= &imatex[shi->thread];
@@ -3745,7 +3745,7 @@ static void textured_face_generate_uv(
}
/* Generate an updated copy of material to use for color sampling. */
-Material *RE_sample_material_init(Material *orig_mat, Scene *scene)
+Material *RE_sample_material_init(const EvaluationContext *eval_ctx, Material *orig_mat, Scene *scene)
{
Tex *tex = NULL;
Material *mat;
@@ -3821,7 +3821,7 @@ Material *RE_sample_material_init(Material *orig_mat, Scene *scene)
unit_m4(dummy_re.viewmat);
unit_m4(dummy_re.winmat);
dummy_re.winx = dummy_re.winy = 128;
- cache_pointdensity(&dummy_re, tex->pd);
+ cache_pointdensity(eval_ctx, &dummy_re, tex->pd);
}
/* update image sequences and movies */
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index 199322795f3..2fbfcc64c8f 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -1482,9 +1482,10 @@ ObjectInstanceRen *RE_addRenderInstance(
return obi;
}
-void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3])
+void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *random, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3])
{
*index = obi->part_index;
+ *random = BLI_hash_int_01(obi->part_index);
*age = obi->part_age;
*lifetime = obi->part_lifetime;
copy_v3_v3(co, obi->part_co);
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
index 6dd7e2c152d..fb441662829 100644
--- a/source/blender/render/intern/source/shadbuf.c
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -40,7 +40,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLI_jitter.h"
+#include "BLI_jitter_2d.h"
#include "BLI_memarena.h"
#include "BLI_rand.h"
#include "BLI_utildefines.h"
@@ -787,10 +787,10 @@ void makeshadowbuf(Render *re, LampRen *lar)
shb->totbuf= lar->buffers;
/* jitter, weights - not threadsafe! */
- BLI_lock_thread(LOCK_CUSTOM1);
+ BLI_thread_lock(LOCK_CUSTOM1);
shb->jit= give_jitter_tab(get_render_shadow_samples(&re->r, shb->samp));
make_jitter_weight_tab(re, shb, lar->filtertype);
- BLI_unlock_thread(LOCK_CUSTOM1);
+ BLI_thread_unlock(LOCK_CUSTOM1);
if (shb->totbuf==4) jitbuf= give_jitter_tab(2);
else if (shb->totbuf==9) jitbuf= give_jitter_tab(3);
@@ -814,21 +814,21 @@ static void *do_shadow_thread(void *re_v)
LampRen *lar;
do {
- BLI_lock_thread(LOCK_CUSTOM1);
+ BLI_thread_lock(LOCK_CUSTOM1);
for (lar=re->lampren.first; lar; lar=lar->next) {
if (lar->shb && !lar->thread_assigned) {
lar->thread_assigned= 1;
break;
}
}
- BLI_unlock_thread(LOCK_CUSTOM1);
+ BLI_thread_unlock(LOCK_CUSTOM1);
/* if type is irregular, this only sets the perspective matrix and autoclips */
if (lar) {
makeshadowbuf(re, lar);
- BLI_lock_thread(LOCK_CUSTOM1);
+ BLI_thread_lock(LOCK_CUSTOM1);
lar->thread_ready= 1;
- BLI_unlock_thread(LOCK_CUSTOM1);
+ BLI_thread_unlock(LOCK_CUSTOM1);
}
} while (lar && !re->test_break(re->tbh));
@@ -878,10 +878,10 @@ void threaded_makeshadowbufs(Render *re)
lar->thread_ready= 0;
}
- BLI_init_threads(&threads, do_shadow_thread, totthread);
+ BLI_threadpool_init(&threads, do_shadow_thread, totthread);
for (a=0; a<totthread; a++)
- BLI_insert_thread(&threads, re);
+ BLI_threadpool_insert(&threads, re);
/* keep rendering as long as there are shadow buffers not ready */
do {
@@ -890,14 +890,14 @@ void threaded_makeshadowbufs(Render *re)
PIL_sleep_ms(50);
- BLI_lock_thread(LOCK_CUSTOM1);
+ BLI_thread_lock(LOCK_CUSTOM1);
for (lar=re->lampren.first; lar; lar= lar->next)
if (lar->shb && !lar->thread_ready)
break;
- BLI_unlock_thread(LOCK_CUSTOM1);
+ BLI_thread_unlock(LOCK_CUSTOM1);
} while (lar);
- BLI_end_threads(&threads);
+ BLI_threadpool_end(&threads);
/* unset threadsafety */
re->test_break= test_break;
diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c
index 26ca3ad50e0..c29da9b17c6 100644
--- a/source/blender/render/intern/source/sss.c
+++ b/source/blender/render/intern/source/sss.c
@@ -973,9 +973,9 @@ void sss_add_points(Render *re, float (*co)[3], float (*color)[3], float *area,
p->area= area;
p->totpoint= totpoint;
- BLI_lock_thread(LOCK_CUSTOM1);
+ BLI_thread_lock(LOCK_CUSTOM1);
BLI_addtail(re->sss_points, p);
- BLI_unlock_thread(LOCK_CUSTOM1);
+ BLI_thread_unlock(LOCK_CUSTOM1);
}
}
diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c
index 1022aeeec66..c45bde300e7 100644
--- a/source/blender/render/intern/source/voxeldata.c
+++ b/source/blender/render/intern/source/voxeldata.c
@@ -61,7 +61,7 @@
#include "BPH_mass_spring.h"
#include "DNA_texture_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_modifier_types.h"
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index f39936dc01f..e948662df00 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -42,7 +42,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLI_jitter.h"
+#include "BLI_jitter_2d.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
@@ -2642,559 +2642,6 @@ void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(vo
zbuf_free_span(&zspan);
}
-/* ******************** VECBLUR ACCUM BUF ************************* */
-
-typedef struct DrawBufPixel {
- const float *colpoin;
- float alpha;
-} DrawBufPixel;
-
-
-static void zbuf_fill_in_rgba(ZSpan *zspan, DrawBufPixel *col, float *v1, float *v2, float *v3, float *v4)
-{
- DrawBufPixel *rectpofs, *rp;
- double zxd, zyd, zy0, zverg;
- float x0, y0, z0;
- float x1, y1, z1, x2, y2, z2, xx1;
- const float *span1, *span2;
- float *rectzofs, *rz;
- int x, y;
- int sn1, sn2, rectx, my0, my2;
-
- /* init */
- zbuf_init_span(zspan);
-
- /* set spans */
- zbuf_add_to_span(zspan, v1, v2);
- zbuf_add_to_span(zspan, v2, v3);
- zbuf_add_to_span(zspan, v3, v4);
- zbuf_add_to_span(zspan, v4, v1);
-
- /* clipped */
- if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
-
- my0 = max_ii(zspan->miny1, zspan->miny2);
- my2 = min_ii(zspan->maxy1, zspan->maxy2);
-
- // printf("my %d %d\n", my0, my2);
- if (my2<my0) return;
-
- /* ZBUF DX DY, in floats still */
- x1= v1[0]- v2[0];
- x2= v2[0]- v3[0];
- y1= v1[1]- v2[1];
- y2= v2[1]- v3[1];
- z1= v1[2]- v2[2];
- z2= v2[2]- v3[2];
- x0= y1*z2-z1*y2;
- y0= z1*x2-x1*z2;
- z0= x1*y2-y1*x2;
-
- if (z0==0.0f) return;
-
- xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
-
- zxd= -(double)x0/(double)z0;
- zyd= -(double)y0/(double)z0;
- zy0= ((double)my2)*zyd + (double)xx1;
-
- /* start-offset in rect */
- rectx= zspan->rectx;
- rectzofs= (float *)(zspan->rectz + rectx*my2);
- rectpofs= ((DrawBufPixel *)zspan->rectp) + rectx*my2;
-
- /* correct span */
- sn1= (my0 + my2)/2;
- if (zspan->span1[sn1] < zspan->span2[sn1]) {
- span1= zspan->span1+my2;
- span2= zspan->span2+my2;
- }
- else {
- span1= zspan->span2+my2;
- span2= zspan->span1+my2;
- }
-
- for (y=my2; y>=my0; y--, span1--, span2--) {
-
- sn1= floor(*span1);
- sn2= floor(*span2);
- sn1++;
-
- if (sn2>=rectx) sn2= rectx-1;
- if (sn1<0) sn1= 0;
-
- if (sn2>=sn1) {
- zverg= (double)sn1*zxd + zy0;
- rz= rectzofs+sn1;
- rp= rectpofs+sn1;
- x= sn2-sn1;
-
- while (x>=0) {
- if (zverg < (double)*rz) {
- *rz= zverg;
- *rp= *col;
- }
- zverg+= zxd;
- rz++;
- rp++;
- x--;
- }
- }
-
- zy0-=zyd;
- rectzofs-= rectx;
- rectpofs-= rectx;
- }
-}
-
-/* char value==255 is filled in, rest should be zero */
-/* returns alpha values, but sets alpha to 1 for zero alpha pixels that have an alpha value as neighbor */
-void antialias_tagbuf(int xsize, int ysize, char *rectmove)
-{
- char *row1, *row2, *row3;
- char prev, next;
- int a, x, y, step;
-
- /* 1: tag pixels to be candidate for AA */
- for (y=2; y<ysize; y++) {
- /* setup rows */
- row1= rectmove + (y-2)*xsize;
- row2= row1 + xsize;
- row3= row2 + xsize;
- for (x=2; x<xsize; x++, row1++, row2++, row3++) {
- if (row2[1]) {
- if (row2[0]==0 || row2[2]==0 || row1[1]==0 || row3[1]==0)
- row2[1]= 128;
- }
- }
- }
-
- /* 2: evaluate horizontal scanlines and calculate alphas */
- row1= rectmove;
- for (y=0; y<ysize; y++) {
- row1++;
- for (x=1; x<xsize; x++, row1++) {
- if (row1[0]==128 && row1[1]==128) {
- /* find previous color and next color and amount of steps to blend */
- prev= row1[-1];
- step= 1;
- while (x+step<xsize && row1[step]==128)
- step++;
-
- if (x+step!=xsize) {
- /* now we can blend values */
- next= row1[step];
-
- /* note, prev value can be next value, but we do this loop to clear 128 then */
- for (a=0; a<step; a++) {
- int fac, mfac;
-
- fac= ((a+1)<<8)/(step+1);
- mfac= 255-fac;
-
- row1[a]= (prev*mfac + next*fac)>>8;
- }
- }
- }
- }
- }
-
- /* 3: evaluate vertical scanlines and calculate alphas */
- /* use for reading a copy of the original tagged buffer */
- for (x=0; x<xsize; x++) {
- row1= rectmove + x+xsize;
-
- for (y=1; y<ysize; y++, row1+=xsize) {
- if (row1[0]==128 && row1[xsize]==128) {
- /* find previous color and next color and amount of steps to blend */
- prev= row1[-xsize];
- step= 1;
- while (y+step<ysize && row1[step*xsize]==128)
- step++;
-
- if (y+step!=ysize) {
- /* now we can blend values */
- next= row1[step*xsize];
- /* note, prev value can be next value, but we do this loop to clear 128 then */
- for (a=0; a<step; a++) {
- int fac, mfac;
-
- fac= ((a+1)<<8)/(step+1);
- mfac= 255-fac;
-
- row1[a*xsize]= (prev*mfac + next*fac)>>8;
- }
- }
- }
- }
- }
-
- /* last: pixels with 0 we fill in zbuffer, with 1 we skip for mask */
- for (y=2; y<ysize; y++) {
- /* setup rows */
- row1= rectmove + (y-2)*xsize;
- row2= row1 + xsize;
- row3= row2 + xsize;
- for (x=2; x<xsize; x++, row1++, row2++, row3++) {
- if (row2[1]==0) {
- if (row2[0]>1 || row2[2]>1 || row1[1]>1 || row3[1]>1)
- row2[1]= 1;
- }
- }
- }
-}
-
-/* in: two vectors, first vector points from origin back in time, 2nd vector points to future */
-/* we make this into 3 points, center point is (0, 0) */
-/* and offset the center point just enough to make curve go through midpoint */
-
-static void quad_bezier_2d(float *result, float *v1, float *v2, float *ipodata)
-{
- float p1[2], p2[2], p3[2];
-
- p3[0]= -v2[0];
- p3[1]= -v2[1];
-
- p1[0]= v1[0];
- p1[1]= v1[1];
-
- /* official formula 2*p2 - 0.5*p1 - 0.5*p3 */
- p2[0]= -0.5f*p1[0] - 0.5f*p3[0];
- p2[1]= -0.5f*p1[1] - 0.5f*p3[1];
-
- result[0]= ipodata[0]*p1[0] + ipodata[1]*p2[0] + ipodata[2]*p3[0];
- result[1]= ipodata[0]*p1[1] + ipodata[1]*p2[1] + ipodata[2]*p3[1];
-}
-
-static void set_quad_bezier_ipo(float fac, float *data)
-{
- float mfac= (1.0f-fac);
-
- data[0]= mfac*mfac;
- data[1]= 2.0f*mfac*fac;
- data[2]= fac*fac;
-}
-
-void RE_zbuf_accumulate_vecblur(
- NodeBlurData *nbd, int xsize, int ysize, float *newrect,
- const float *imgrect, float *vecbufrect, const float *zbufrect)
-{
- ZSpan zspan;
- DrawBufPixel *rectdraw, *dr;
- static float jit[256][2];
- float v1[3], v2[3], v3[3], v4[3], fx, fy;
- const float *dimg, *dz, *ro;
- float *rectvz, *dvz, *dvec1, *dvec2, *dz1, *dz2, *rectz;
- float *minvecbufrect= NULL, *rectweight, *rw, *rectmax, *rm;
- float maxspeedsq= (float)nbd->maxspeed*nbd->maxspeed;
- int y, x, step, maxspeed=nbd->maxspeed, samples= nbd->samples;
- int tsktsk= 0;
- static int firsttime= 1;
- char *rectmove, *dm;
-
- zbuf_alloc_span(&zspan, xsize, ysize, 1.0f);
- zspan.zmulx= ((float)xsize)/2.0f;
- zspan.zmuly= ((float)ysize)/2.0f;
- zspan.zofsx= 0.0f;
- zspan.zofsy= 0.0f;
-
- /* the buffers */
- rectz= MEM_mapallocN(sizeof(float)*xsize*ysize, "zbuf accum");
- zspan.rectz= (int *)rectz;
-
- rectmove= MEM_mapallocN(xsize*ysize, "rectmove");
- rectdraw= MEM_mapallocN(sizeof(DrawBufPixel)*xsize*ysize, "rect draw");
- zspan.rectp= (int *)rectdraw;
-
- rectweight= MEM_mapallocN(sizeof(float)*xsize*ysize, "rect weight");
- rectmax= MEM_mapallocN(sizeof(float)*xsize*ysize, "rect max");
-
- /* debug... check if PASS_VECTOR_MAX still is in buffers */
- dvec1= vecbufrect;
- for (x= 4*xsize*ysize; x>0; x--, dvec1++) {
- if (dvec1[0]==PASS_VECTOR_MAX) {
- dvec1[0]= 0.0f;
- tsktsk= 1;
- }
- }
- if (tsktsk) printf("Found uninitialized speed in vector buffer... fixed.\n");
-
- /* min speed? then copy speedbuffer to recalculate speed vectors */
- if (nbd->minspeed) {
- float minspeed= (float)nbd->minspeed;
- float minspeedsq= minspeed*minspeed;
-
- minvecbufrect= MEM_mapallocN(4*sizeof(float)*xsize*ysize, "minspeed buf");
-
- dvec1= vecbufrect;
- dvec2= minvecbufrect;
- for (x= 2*xsize*ysize; x>0; x--, dvec1+=2, dvec2+=2) {
- if (dvec1[0]==0.0f && dvec1[1]==0.0f) {
- dvec2[0]= dvec1[0];
- dvec2[1]= dvec1[1];
- }
- else {
- float speedsq= dvec1[0]*dvec1[0] + dvec1[1]*dvec1[1];
- if (speedsq <= minspeedsq) {
- dvec2[0]= 0.0f;
- dvec2[1]= 0.0f;
- }
- else {
- speedsq = 1.0f - minspeed / sqrtf(speedsq);
- dvec2[0]= speedsq*dvec1[0];
- dvec2[1]= speedsq*dvec1[1];
- }
- }
- }
- SWAP(float *, minvecbufrect, vecbufrect);
- }
-
- /* make vertex buffer with averaged speed and zvalues */
- rectvz= MEM_mapallocN(4*sizeof(float)*(xsize+1)*(ysize+1), "vertices");
- dvz= rectvz;
- for (y=0; y<=ysize; y++) {
-
- if (y==0)
- dvec1= vecbufrect + 4*y*xsize;
- else
- dvec1= vecbufrect + 4*(y-1)*xsize;
-
- if (y==ysize)
- dvec2= vecbufrect + 4*(y-1)*xsize;
- else
- dvec2= vecbufrect + 4*y*xsize;
-
- for (x=0; x<=xsize; x++) {
-
- /* two vectors, so a step loop */
- for (step=0; step<2; step++, dvec1+=2, dvec2+=2, dvz+=2) {
- /* average on minimal speed */
- int div= 0;
-
- if (x!=0) {
- if (dvec1[-4]!=0.0f || dvec1[-3]!=0.0f) {
- dvz[0]= dvec1[-4];
- dvz[1]= dvec1[-3];
- div++;
- }
- if (dvec2[-4]!=0.0f || dvec2[-3]!=0.0f) {
- if (div==0) {
- dvz[0]= dvec2[-4];
- dvz[1]= dvec2[-3];
- div++;
- }
- else if ( (ABS(dvec2[-4]) + ABS(dvec2[-3]))< (ABS(dvz[0]) + ABS(dvz[1])) ) {
- dvz[0]= dvec2[-4];
- dvz[1]= dvec2[-3];
- }
- }
- }
-
- if (x!=xsize) {
- if (dvec1[0]!=0.0f || dvec1[1]!=0.0f) {
- if (div==0) {
- dvz[0]= dvec1[0];
- dvz[1]= dvec1[1];
- div++;
- }
- else if ( (ABS(dvec1[0]) + ABS(dvec1[1]))< (ABS(dvz[0]) + ABS(dvz[1])) ) {
- dvz[0]= dvec1[0];
- dvz[1]= dvec1[1];
- }
- }
- if (dvec2[0]!=0.0f || dvec2[1]!=0.0f) {
- if (div==0) {
- dvz[0]= dvec2[0];
- dvz[1]= dvec2[1];
- }
- else if ( (ABS(dvec2[0]) + ABS(dvec2[1]))< (ABS(dvz[0]) + ABS(dvz[1])) ) {
- dvz[0]= dvec2[0];
- dvz[1]= dvec2[1];
- }
- }
- }
- if (maxspeed) {
- float speedsq= dvz[0]*dvz[0] + dvz[1]*dvz[1];
- if (speedsq > maxspeedsq) {
- speedsq = (float)maxspeed / sqrtf(speedsq);
- dvz[0]*= speedsq;
- dvz[1]*= speedsq;
- }
- }
- }
- }
- }
-
- /* set border speeds to keep border speeds on border */
- dz1= rectvz;
- dz2= rectvz+4*(ysize)*(xsize+1);
- for (x=0; x<=xsize; x++, dz1+=4, dz2+=4) {
- dz1[1]= 0.0f;
- dz2[1]= 0.0f;
- dz1[3]= 0.0f;
- dz2[3]= 0.0f;
- }
- dz1= rectvz;
- dz2= rectvz+4*(xsize);
- for (y=0; y<=ysize; y++, dz1+=4*(xsize+1), dz2+=4*(xsize+1)) {
- dz1[0]= 0.0f;
- dz2[0]= 0.0f;
- dz1[2]= 0.0f;
- dz2[2]= 0.0f;
- }
-
- /* tag moving pixels, only these faces we draw */
- dm= rectmove;
- dvec1= vecbufrect;
- for (x=xsize*ysize; x>0; x--, dm++, dvec1+=4) {
- if ((dvec1[0]!=0.0f || dvec1[1]!=0.0f || dvec1[2]!=0.0f || dvec1[3]!=0.0f))
- *dm= 255;
- }
-
- antialias_tagbuf(xsize, ysize, rectmove);
-
- /* has to become static, the init-jit calls a random-seed, screwing up texture noise node */
- if (firsttime) {
- firsttime= 0;
- BLI_jitter_init(jit, 256);
- }
-
- memset(newrect, 0, sizeof(float)*xsize*ysize*4);
-
- /* accumulate */
- samples/= 2;
- for (step= 1; step<=samples; step++) {
- float speedfac= 0.5f*nbd->fac*(float)step/(float)(samples+1);
- int side;
-
- for (side=0; side<2; side++) {
- float blendfac, ipodata[4];
-
- /* clear zbuf, if we draw future we fill in not moving pixels */
- if (0)
- for (x= xsize*ysize-1; x>=0; x--) rectz[x]= 10e16;
- else
- for (x= xsize*ysize-1; x>=0; x--) {
- if (rectmove[x]==0)
- rectz[x]= zbufrect[x];
- else
- rectz[x]= 10e16;
- }
-
- /* clear drawing buffer */
- for (x= xsize*ysize-1; x>=0; x--) rectdraw[x].colpoin= NULL;
-
- dimg= imgrect;
- dm= rectmove;
- dz= zbufrect;
- dz1= rectvz;
- dz2= rectvz + 4*(xsize + 1);
-
- if (side) {
- if (nbd->curved==0) {
- dz1+= 2;
- dz2+= 2;
- }
- speedfac= -speedfac;
- }
-
- set_quad_bezier_ipo(0.5f + 0.5f*speedfac, ipodata);
-
- for (fy= -0.5f+jit[step & 255][0], y=0; y<ysize; y++, fy+=1.0f) {
- for (fx= -0.5f+jit[step & 255][1], x=0; x<xsize; x++, fx+=1.0f, dimg+=4, dz1+=4, dz2+=4, dm++, dz++) {
- if (*dm>1) {
- float jfx = fx + 0.5f;
- float jfy = fy + 0.5f;
- DrawBufPixel col;
-
- /* make vertices */
- if (nbd->curved) { /* curved */
- quad_bezier_2d(v1, dz1, dz1+2, ipodata);
- v1[0]+= jfx; v1[1]+= jfy; v1[2]= *dz;
-
- quad_bezier_2d(v2, dz1+4, dz1+4+2, ipodata);
- v2[0]+= jfx+1.0f; v2[1]+= jfy; v2[2]= *dz;
-
- quad_bezier_2d(v3, dz2+4, dz2+4+2, ipodata);
- v3[0]+= jfx+1.0f; v3[1]+= jfy+1.0f; v3[2]= *dz;
-
- quad_bezier_2d(v4, dz2, dz2+2, ipodata);
- v4[0]+= jfx; v4[1]+= jfy+1.0f; v4[2]= *dz;
- }
- else {
- v1[0]= speedfac*dz1[0]+jfx; v1[1]= speedfac*dz1[1]+jfy; v1[2]= *dz;
- v2[0]= speedfac*dz1[4]+jfx+1.0f; v2[1]= speedfac*dz1[5]+jfy; v2[2]= *dz;
- v3[0]= speedfac*dz2[4]+jfx+1.0f; v3[1]= speedfac*dz2[5]+jfy+1.0f; v3[2]= *dz;
- v4[0]= speedfac*dz2[0]+jfx; v4[1]= speedfac*dz2[1]+jfy+1.0f; v4[2]= *dz;
- }
- if (*dm==255) col.alpha= 1.0f;
- else if (*dm<2) col.alpha= 0.0f;
- else col.alpha= ((float)*dm)/255.0f;
- col.colpoin= dimg;
-
- zbuf_fill_in_rgba(&zspan, &col, v1, v2, v3, v4);
- }
- }
- dz1+=4;
- dz2+=4;
- }
-
- /* blend with a falloff. this fixes the ugly effect you get with
- * a fast moving object. then it looks like a solid object overlayed
- * over a very transparent moving version of itself. in reality, the
- * whole object should become transparent if it is moving fast, be
- * we don't know what is behind it so we don't do that. this hack
- * overestimates the contribution of foreground pixels but looks a
- * bit better without a sudden cutoff. */
- blendfac= ((samples - step)/(float)samples);
- /* smoothstep to make it look a bit nicer as well */
- blendfac= 3.0f*pow(blendfac, 2.0f) - 2.0f*pow(blendfac, 3.0f);
-
- /* accum */
- rw= rectweight;
- rm= rectmax;
- for (dr= rectdraw, dz2=newrect, x= xsize*ysize-1; x>=0; x--, dr++, dz2+=4, rw++, rm++) {
- if (dr->colpoin) {
- float bfac= dr->alpha*blendfac;
-
- dz2[0] += bfac*dr->colpoin[0];
- dz2[1] += bfac*dr->colpoin[1];
- dz2[2] += bfac*dr->colpoin[2];
- dz2[3] += bfac*dr->colpoin[3];
-
- *rw += bfac;
- *rm= MAX2(*rm, bfac);
- }
- }
- }
- }
-
- /* blend between original images and accumulated image */
- rw= rectweight;
- rm= rectmax;
- ro= imgrect;
- dm= rectmove;
- for (dz2=newrect, x= xsize*ysize-1; x>=0; x--, dz2+=4, ro+=4, rw++, rm++, dm++) {
- float mfac = *rm;
- float fac = (*rw == 0.0f)? 0.0f: mfac/(*rw);
- float nfac = 1.0f - mfac;
-
- dz2[0]= fac*dz2[0] + nfac*ro[0];
- dz2[1]= fac*dz2[1] + nfac*ro[1];
- dz2[2]= fac*dz2[2] + nfac*ro[2];
- dz2[3]= fac*dz2[3] + nfac*ro[3];
- }
-
- MEM_freeN(rectz);
- MEM_freeN(rectmove);
- MEM_freeN(rectdraw);
- MEM_freeN(rectvz);
- MEM_freeN(rectweight);
- MEM_freeN(rectmax);
- if (minvecbufrect) MEM_freeN(vecbufrect); /* rects were swapped! */
- zbuf_free_span(&zspan);
-}
-
/* ******************** ABUF ************************* */
/**
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index 059055daea9..da61a201ef6 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -35,6 +35,7 @@ set(INC
../compositor
../depsgraph
../editors/include
+ ../draw
../gpu
../imbuf
../makesdna
@@ -42,6 +43,7 @@ set(INC
../nodes
../render/extern/include
../../gameengine/BlenderRoutines
+ ../../../intern/clog
../../../intern/ghost
../../../intern/guardedalloc
../../../intern/glew-mx
@@ -93,7 +95,6 @@ set(SRC
wm_event_system.h
wm_event_types.h
wm_files.h
- wm_subwindow.h
wm_window.h
manipulators/WM_manipulator_api.h
manipulators/WM_manipulator_types.h
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 7a66cc04014..377d274a712 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -67,6 +67,7 @@ struct ARegion;
struct ScrArea;
struct Main;
struct bToolDef;
+struct ViewLayer;
#ifdef WITH_INPUT_NDOF
struct wmNDOFMotionData;
@@ -114,8 +115,17 @@ void WM_window_set_active_layout(
struct wmWindow *win, struct WorkSpace *workspace, struct WorkSpaceLayout *layout) ATTR_NONNULL(1);
struct bScreen *WM_window_get_active_screen(const struct wmWindow *win) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
void WM_window_set_active_screen(struct wmWindow *win, struct WorkSpace *workspace, struct bScreen *screen) ATTR_NONNULL(1);
+
+struct ViewLayer *WM_window_get_active_view_layer_ex(const struct wmWindow *win, struct Scene **r_scene) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
+struct ViewLayer *WM_window_get_active_view_layer(const struct wmWindow *win) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
+
bool WM_window_is_temp_screen(const struct wmWindow *win) ATTR_WARN_UNUSED_RESULT;
+void *WM_opengl_context_create(void);
+void WM_opengl_context_dispose(void *context);
+void WM_opengl_context_activate(void *context);
+void WM_opengl_context_release(void *context);
+
/* defines for 'type' WM_window_open_temp */
enum {
WM_WINDOW_RENDER = 1,
@@ -138,7 +148,7 @@ void WM_file_autoexec_init(const char *filepath);
bool WM_file_read(struct bContext *C, const char *filepath, struct ReportList *reports);
void WM_autosave_init(struct wmWindowManager *wm);
void WM_recover_last_session(struct bContext *C, struct ReportList *reports);
-void WM_file_tag_modified(const struct bContext *C);
+void WM_file_tag_modified(void);
void WM_lib_reload(struct Library *lib, struct bContext *C, struct ReportList *reports);
@@ -212,7 +222,7 @@ enum {
struct wmEventHandler *WM_event_add_dropbox_handler(ListBase *handlers, ListBase *dropboxes);
/* mouse */
-void WM_event_add_mousemove(struct bContext *C);
+void WM_event_add_mousemove(const struct bContext *C);
bool WM_event_is_modal_tweak_exit(const struct wmEvent *event, int tweak_event);
bool WM_event_is_last_mousemove(const struct wmEvent *event);
@@ -413,6 +423,7 @@ struct MenuType *WM_menutype_find(const char *idname, bool quiet);
bool WM_menutype_add(struct MenuType *mt);
void WM_menutype_freelink(struct MenuType *mt);
void WM_menutype_free(void);
+bool WM_menutype_poll(struct bContext *C, struct MenuType *mt);
/* wm_gesture_ops.c */
int WM_gesture_border_invoke (struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
@@ -454,15 +465,17 @@ struct wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(s
void (*copy)(struct wmDrag *, struct wmDropBox *));
ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid);
- /* Set a subwindow active in pixelspace view, with optional scissor subset */
-void wmSubWindowSet (struct wmWindow *win, int swinid);
-void wmSubWindowScissorSet (struct wmWindow *win, int swinid, const struct rcti *srct, bool srct_pad);
+ /* Set OpenGL viewport and scissor */
+void wmViewport(const struct rcti *rect);
+void wmPartialViewport(rcti *drawrct, const rcti *winrct, const rcti *partialrct);
+void wmWindowViewport(struct wmWindow *win);
/* OpenGL utilities with safety check */
void wmOrtho2 (float x1, float x2, float y1, float y2);
/* use for conventions (avoid hard-coded offsets all over) */
void wmOrtho2_region_pixelspace(const struct ARegion *ar);
void wmOrtho2_pixelspace(const float x, const float y);
+void wmGetProjectionMatrix(float mat[4][4], const struct rcti *winrct);
/* threaded Jobs Manager */
enum {
@@ -493,6 +506,7 @@ enum {
WM_JOB_TYPE_POINTCACHE,
WM_JOB_TYPE_DPAINT_BAKE,
WM_JOB_TYPE_ALEMBIC,
+ WM_JOB_TYPE_SHADER_COMPILATION,
/* add as needed, screencast, seq proxy build
* if having hard coded values is a problem */
};
diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h
index 8a94472aaf5..b4d4d55479d 100644
--- a/source/blender/windowmanager/WM_keymap.h
+++ b/source/blender/windowmanager/WM_keymap.h
@@ -76,7 +76,8 @@ wmKeyMap *WM_keymap_find_all(const struct bContext *C, const char *idname, int s
wmKeyMap *WM_keymap_active(struct wmWindowManager *wm, struct wmKeyMap *keymap);
wmKeyMap *WM_keymap_guess_opname(const struct bContext *C, const char *opname);
bool WM_keymap_remove(struct wmKeyConfig *keyconfig, struct wmKeyMap *keymap);
-
+bool WM_keymap_poll(struct bContext *C, struct wmKeyMap *keymap);
+
wmKeyMapItem *WM_keymap_item_find_id(struct wmKeyMap *keymap, int id);
int WM_keymap_item_compare(struct wmKeyMapItem *k1, struct wmKeyMapItem *k2);
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 74703daeb9c..383744b898a 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -115,6 +115,7 @@ struct ImBuf;
#include "RNA_types.h"
#include "DNA_listBase.h"
+#include "DNA_vec_types.h"
#include "BLI_compiler_attrs.h"
/* exported types for WM */
@@ -214,7 +215,6 @@ typedef struct wmNotifier {
struct wmWindowManager *wm;
struct wmWindow *window;
- int swinid; /* can't rely on this, notifiers can be added without context, swinid of 0 */
unsigned int category, data, subtype, action;
void *reference;
@@ -424,7 +424,7 @@ typedef struct wmGesture {
struct wmGesture *next, *prev;
int event_type; /* event->type */
int type; /* gesture type define */
- int swinid; /* initial subwindow id where it started */
+ rcti winrct; /* bounds of region to draw gesture within */
int points; /* optional, amount of points stored */
int points_alloc; /* optional, maximum amount of points stored */
int modal_state;
@@ -522,6 +522,10 @@ typedef struct wmNDOFMotionData {
} wmNDOFMotionData;
#endif /* WITH_INPUT_NDOF */
+typedef enum { /* Timer flags */
+ WM_TIMER_NO_FREE_CUSTOM_DATA = 1 << 0, /* Do not attempt to free customdata pointer even if non-NULL. */
+} wmTimerFlags;
+
typedef struct wmTimer {
struct wmTimer *next, *prev;
@@ -529,6 +533,7 @@ typedef struct wmTimer {
double timestep; /* set by timer user */
int event_type; /* set by timer user, goes to event system */
+ wmTimerFlags flags; /* Various flags controlling timer options, see below. */
void *customdata; /* set by timer user, to allow custom values */
double duration; /* total running time in seconds */
@@ -537,7 +542,7 @@ typedef struct wmTimer {
double ltime; /* internal, last time timer was activated */
double ntime; /* internal, next time we want to activate the timer */
double stime; /* internal, when the timer started */
- int sleep; /* internal, put timers to sleep when needed */
+ bool sleep; /* internal, put timers to sleep when needed */
} wmTimer;
typedef struct wmOperatorType {
@@ -728,6 +733,14 @@ typedef struct RecentFile {
char *filepath;
} RecentFile;
+/* Logging */
+struct CLG_LogRef;
+/* wm_init_exit.c */
+extern struct CLG_LogRef *WM_LOG_OPERATORS;
+extern struct CLG_LogRef *WM_LOG_HANDLERS;
+extern struct CLG_LogRef *WM_LOG_EVENTS;
+extern struct CLG_LogRef *WM_LOG_KEYMAPS;
+
#ifdef __cplusplus
}
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 623a7af5165..27107299863 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -63,6 +63,7 @@
#include "wm.h"
#include "ED_screen.h"
+#include "BKE_undo_system.h"
#ifdef WITH_PYTHON
#include "BPY_extern.h"
@@ -339,6 +340,22 @@ void WM_menutype_free(void)
menutypes_hash = NULL;
}
+bool WM_menutype_poll(bContext *C, MenuType *mt)
+{
+ /* If we're tagged, only use compatible. */
+ if (mt->owner_id[0] != '\0') {
+ const WorkSpace *workspace = CTX_wm_workspace(C);
+ if (BKE_workspace_owner_id_check(workspace, mt->owner_id) == false) {
+ return false;
+ }
+ }
+
+ if (mt->poll != NULL) {
+ return mt->poll(C, mt);
+ }
+ return true;
+}
+
/* ****************************************** */
void WM_keymap_init(bContext *C)
@@ -490,7 +507,12 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
WM_drag_free_list(&wm->drags);
wm_reports_free(wm);
-
+
+ if (wm->undo_stack) {
+ BKE_undosys_stack_destroy(wm->undo_stack);
+ wm->undo_stack = NULL;
+ }
+
if (C && CTX_wm_manager(C) == wm) CTX_wm_manager_set(C, NULL);
}
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index b12dbf7b021..ed276aa690d 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -95,7 +95,7 @@ static void wm_paintcursor_draw(bContext *C, ARegion *ar)
bScreen *screen = WM_window_get_active_screen(win);
wmPaintCursor *pc;
- if (ar->swinid && screen->subwinactive == ar->swinid) {
+ if (ar->visible && ar == screen->active_region) {
for (pc = wm->paintcursors.first; pc; pc = pc->next) {
if (pc->poll == NULL || pc->poll(C)) {
ARegion *ar_other = CTX_wm_region(C);
@@ -216,7 +216,7 @@ static void wm_method_draw_full(bContext *C, wmWindow *win)
CTX_wm_area_set(C, sa);
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->swinid) {
+ if (ar->visible) {
CTX_wm_region_set(C, ar);
ED_region_do_draw(C, ar);
ar->do_draw = false;
@@ -235,7 +235,7 @@ static void wm_method_draw_full(bContext *C, wmWindow *win)
/* draw overlapping regions */
for (ar = screen->regionbase.first; ar; ar = ar->next) {
- if (ar->swinid) {
+ if (ar->visible) {
CTX_wm_menu_set(C, ar);
ED_region_do_draw(C, ar);
ar->do_draw = false;
@@ -295,7 +295,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
/* after backbuffer selection draw, we need to redraw */
for (sa = screen->areabase.first; sa; sa = sa->next)
for (ar = sa->regionbase.first; ar; ar = ar->next)
- if (ar->swinid && !wm_area_test_invalid_backbuf(sa))
+ if (ar->visible && !wm_area_test_invalid_backbuf(sa))
ED_region_tag_redraw(ar);
/* flush overlapping regions */
@@ -303,17 +303,17 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
/* flush redraws of area regions up to overlapping regions */
for (sa = screen->areabase.first; sa; sa = sa->next)
for (ar = sa->regionbase.first; ar; ar = ar->next)
- if (ar->swinid && ar->do_draw)
+ if (ar->visible && ar->do_draw)
wm_flush_regions_up(screen, &ar->winrct);
/* flush between overlapping regions */
for (ar = screen->regionbase.last; ar; ar = ar->prev)
- if (ar->swinid && ar->do_draw)
+ if (ar->visible && ar->do_draw)
wm_flush_regions_up(screen, &ar->winrct);
/* flush redraws of overlapping regions down to area regions */
for (ar = screen->regionbase.last; ar; ar = ar->prev)
- if (ar->swinid && ar->do_draw)
+ if (ar->visible && ar->do_draw)
wm_flush_regions_down(screen, &ar->winrct);
}
@@ -332,7 +332,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
CTX_wm_area_set(C, sa);
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->swinid) {
+ if (ar->visible) {
if (ar->do_draw) {
CTX_wm_region_set(C, ar);
ED_region_do_draw(C, ar);
@@ -389,7 +389,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
/* draw marked overlapping regions */
for (ar = screen->regionbase.first; ar; ar = ar->next) {
- if (ar->swinid && ar->do_draw) {
+ if (ar->visible && ar->do_draw) {
CTX_wm_menu_set(C, ar);
ED_region_do_draw(C, ar);
ar->do_draw = false;
@@ -430,15 +430,8 @@ static void wm_draw_triple_fail(bContext *C, wmWindow *win)
static bool wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
{
/* compute texture sizes */
- triple->x = WM_window_pixels_x(win);
- triple->y = WM_window_pixels_y(win);
-
-#if USE_TEXTURE_RECTANGLE
- /* GL_TEXTURE_RECTANGLE is part of GL 3.1 so we can use it soon without runtime checks */
- triple->target = GL_TEXTURE_RECTANGLE;
-#else
- triple->target = GL_TEXTURE_2D;
-#endif
+ const int sizex = WM_window_pixels_x(win);
+ const int sizey = WM_window_pixels_y(win);
/* generate texture names */
glGenTextures(1, &triple->bind);
@@ -447,29 +440,25 @@ static bool wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
* there is only one texture in use, which may not be the case */
const GLint maxsize = GPU_max_texture_size();
- if (triple->x > maxsize || triple->y > maxsize) {
+ if (sizex > maxsize || sizey > maxsize) {
printf("WM: failed to allocate texture for triple buffer drawing "
"(texture too large for graphics card).\n");
return false;
}
/* setup actual texture */
- glBindTexture(triple->target, triple->bind);
+ glBindTexture(GL_TEXTURE_2D, triple->bind);
/* no mipmaps */
-#if USE_TEXTURE_RECTANGLE
- /* already has no mipmaps */
-#else
- glTexParameteri(triple->target, GL_TEXTURE_MAX_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
/* GL_TEXTURE_BASE_LEVEL = 0 by default */
-#endif
- glTexParameteri(triple->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(triple->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexImage2D(triple->target, 0, GL_RGB8, triple->x, triple->y, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, sizex, sizey, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
- glBindTexture(triple->target, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
return true;
}
@@ -480,59 +469,31 @@ void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha)
const int sizey = WM_window_pixels_y(win);
/* wmOrtho for the screen has this same offset */
- float ratiox = sizex;
- float ratioy = sizey;
- float halfx = GLA_PIXEL_OFS;
- float halfy = GLA_PIXEL_OFS;
-
-#if USE_TEXTURE_RECTANGLE
- /* texture rectangle has unnormalized coordinates */
-#else
- ratiox /= triple->x;
- ratioy /= triple->y;
- halfx /= triple->x;
- halfy /= triple->y;
-#endif
-
- Gwn_VertFormat *format = immVertexFormat();
- unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const float ratiox = 1.0f;
+ const float ratioy = 1.0f;
+ const float halfx = GLA_PIXEL_OFS / sizex;
+ const float halfy = GLA_PIXEL_OFS / sizey;
const int activeTex = 7; /* arbitrary */
glActiveTexture(GL_TEXTURE0 + activeTex);
- glBindTexture(triple->target, triple->bind);
-
-#if USE_TEXTURE_RECTANGLE
- immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA);
-#else
- immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA);
- /* TODO: make pure 2D version
- * and a 2D_IMAGE (replace, not modulate) version for when alpha = 1.0
- */
-#endif
- immUniform1f("alpha", alpha);
- immUniform1i("image", activeTex);
-
- immBegin(GWN_PRIM_TRI_FAN, 4);
-
- immAttrib2f(texcoord, halfx, halfy);
- immVertex2f(pos, 0.0f, 0.0f);
+ glBindTexture(GL_TEXTURE_2D, triple->bind);
- immAttrib2f(texcoord, ratiox + halfx, halfy);
- immVertex2f(pos, sizex, 0.0f);
+ float x1 = halfx;
+ float x2 = ratiox + halfx;
+ float y1 = halfy;
+ float y2 = ratioy + halfy;
- immAttrib2f(texcoord, ratiox + halfx, ratioy + halfy);
- immVertex2f(pos, sizex, sizey);
+ GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
+ GPU_shader_bind(shader);
- immAttrib2f(texcoord, halfx, ratioy + halfy);
- immVertex2f(pos, 0.0f, sizey);
+ glUniform1i(GPU_shader_get_uniform(shader, "image"), activeTex);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), x1, y1, x2, y2);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), 0.0f, 0.0f, sizex, sizey);
+ glUniform4f(GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_COLOR), alpha, alpha, alpha, alpha);
- immEnd();
- immUnbindProgram();
+ GWN_draw_primitive(GWN_PRIM_TRI_STRIP, 4);
- glBindTexture(triple->target, 0);
- if (activeTex != 0)
- glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, 0);
}
static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple)
@@ -540,10 +501,10 @@ static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple)
const int sizex = WM_window_pixels_x(win);
const int sizey = WM_window_pixels_y(win);
- glBindTexture(triple->target, triple->bind);
+ glBindTexture(GL_TEXTURE_2D, triple->bind);
/* what is GL_READ_BUFFER right now? */
- glCopyTexSubImage2D(triple->target, 0, 0, 0, 0, 0, sizex, sizey);
- glBindTexture(triple->target, 0);
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sizex, sizey);
+ glBindTexture(GL_TEXTURE_2D, 0);
}
static void wm_draw_region_blend(wmWindow *win, ARegion *ar, wmDrawTriple *triple)
@@ -552,9 +513,7 @@ static void wm_draw_region_blend(wmWindow *win, ARegion *ar, wmDrawTriple *tripl
/* region blend always is 1, except when blend timer is running */
if (fac < 1.0f) {
- bScreen *screen = WM_window_get_active_screen(win);
-
- wmSubWindowScissorSet(win, screen->mainwin, &ar->winrct, true);
+ wmViewport(&ar->winrct);
glEnable(GL_BLEND);
wm_triple_draw_textures(win, triple, 1.0f - fac);
@@ -577,7 +536,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
#endif
- wmSubWindowSet(win, screen->mainwin);
+ wmWindowViewport(win);
wm_triple_draw_textures(win, drawdata->triple, 1.0f);
}
@@ -613,7 +572,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
CTX_wm_area_set(C, sa);
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->swinid && ar->do_draw) {
+ if (ar->visible && ar->do_draw) {
if (ar->overlap == false) {
CTX_wm_region_set(C, ar);
ED_region_do_draw(C, ar);
@@ -629,7 +588,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
}
if (copytex) {
- wmSubWindowSet(win, screen->mainwin);
+ wmWindowViewport(win);
wm_triple_copy_textures(win, triple);
}
@@ -637,12 +596,12 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
if (wm->paintcursors.first) {
for (sa = screen->areabase.first; sa; sa = sa->next) {
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->swinid && ar->swinid == screen->subwinactive) {
+ if (ar->visible && ar == screen->active_region) {
CTX_wm_area_set(C, sa);
CTX_wm_region_set(C, ar);
/* make region ready for draw, scissor, pixelspace */
- ED_region_set(C, ar);
+ wmViewport(&ar->winrct);
wm_paintcursor_draw(C, ar);
CTX_wm_region_set(C, NULL);
@@ -651,7 +610,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
}
}
- wmSubWindowSet(win, screen->mainwin);
+ wmWindowViewport(win);
}
/* draw overlapping area regions (always like popups) */
@@ -659,7 +618,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
CTX_wm_area_set(C, sa);
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->swinid && ar->overlap) {
+ if (ar->visible && ar->overlap) {
CTX_wm_region_set(C, ar);
ED_region_do_draw(C, ar);
ar->do_draw = false;
@@ -679,7 +638,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
/* draw floating regions (menus) */
for (ar = screen->regionbase.first; ar; ar = ar->next) {
- if (ar->swinid) {
+ if (ar->visible) {
CTX_wm_menu_set(C, ar);
ED_region_do_draw(C, ar);
ar->do_draw = false;
@@ -719,7 +678,7 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoV
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
#endif
- wmSubWindowSet(win, screen->mainwin);
+ wmWindowViewport(win);
wm_triple_draw_textures(win, drawdata->triple, 1.0f);
}
@@ -784,7 +743,7 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoV
/* draw marked area regions */
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->swinid && ar->do_draw) {
+ if (ar->visible && ar->do_draw) {
if (ar->overlap == false) {
CTX_wm_region_set(C, ar);
@@ -804,7 +763,7 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoV
}
if (copytex) {
- wmSubWindowSet(win, screen->mainwin);
+ wmWindowViewport(win);
wm_triple_copy_textures(win, triple_data);
}
@@ -812,12 +771,12 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoV
if (wm->paintcursors.first) {
for (sa = screen->areabase.first; sa; sa = sa->next) {
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->swinid && ar->swinid == screen->subwinactive) {
+ if (ar->visible && ar == screen->active_region) {
CTX_wm_area_set(C, sa);
CTX_wm_region_set(C, ar);
/* make region ready for draw, scissor, pixelspace */
- ED_region_set(C, ar);
+ wmViewport(&ar->winrct);
wm_paintcursor_draw(C, ar);
CTX_wm_region_set(C, NULL);
@@ -826,7 +785,7 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoV
}
}
- wmSubWindowSet(win, screen->mainwin);
+ wmWindowViewport(win);
}
/* draw overlapping area regions (always like popups) */
@@ -834,7 +793,7 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoV
CTX_wm_area_set(C, sa);
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->swinid && ar->overlap) {
+ if (ar->visible && ar->overlap) {
CTX_wm_region_set(C, ar);
ED_region_do_draw(C, ar);
if (sview == STEREO_RIGHT_ID)
@@ -857,7 +816,7 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoV
/* draw floating regions (menus) */
for (ar = screen->regionbase.first; ar; ar = ar->next) {
- if (ar->swinid) {
+ if (ar->visible) {
CTX_wm_menu_set(C, ar);
ED_region_do_draw(C, ar);
if (sview == STEREO_RIGHT_ID)
@@ -876,7 +835,7 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoV
}
/* copy the ui + overlays */
- wmSubWindowSet(win, screen->mainwin);
+ wmWindowViewport(win);
wm_triple_copy_textures(win, triple_all);
}
@@ -899,7 +858,7 @@ static bool wm_draw_update_test_window(wmWindow *win)
wm_tag_redraw_overlay(win, ar);
ar->do_draw_overlay = false;
}
- if (ar->swinid && ar->do_draw)
+ if (ar->visible && ar->do_draw)
do_draw = true;
}
@@ -907,7 +866,7 @@ static bool wm_draw_update_test_window(wmWindow *win)
for (ar = sa->regionbase.first; ar; ar = ar->next) {
wm_region_test_render_do_draw(scene, depsgraph, sa, ar);
- if (ar->swinid && ar->do_draw)
+ if (ar->visible && ar->do_draw)
do_draw = true;
}
}
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 133ac6564f8..6ec68614116 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -43,6 +43,8 @@
#include "MEM_guardedalloc.h"
+#include "CLG_log.h"
+
#include "GHOST_C-api.h"
#include "BLI_blenlib.h"
@@ -67,6 +69,7 @@
#include "ED_screen.h"
#include "ED_view3d.h"
#include "ED_util.h"
+#include "ED_undo.h"
#include "RNA_access.h"
@@ -182,7 +185,6 @@ static bool wm_test_duplicate_notifier(wmWindowManager *wm, unsigned int type, v
/* XXX: in future, which notifiers to send to other windows? */
void WM_event_add_notifier(const bContext *C, unsigned int type, void *reference)
{
- ARegion *ar;
wmWindowManager *wm = CTX_wm_manager(C);
wmNotifier *note;
@@ -196,10 +198,6 @@ void WM_event_add_notifier(const bContext *C, unsigned int type, void *reference
note->window = CTX_wm_window(C);
- ar = CTX_wm_region(C);
- if (ar)
- note->swinid = ar->swinid;
-
note->category = type & NOTE_CATEGORY;
note->data = type & NOTE_DATA;
note->subtype = type & NOTE_SUBTYPE;
@@ -339,7 +337,8 @@ void wm_event_do_refresh_wm_and_depsgraph(bContext *C)
scene->customdata_mask |= scene->customdata_mask_modal;
WorkSpace *workspace = WM_window_get_active_workspace(win);
- BKE_workspace_update_tagged(bmain->eval_ctx, bmain, workspace, scene);
+
+ BKE_workspace_update_tagged(bmain, workspace, scene);
}
}
@@ -430,9 +429,8 @@ void wm_event_do_notifiers(bContext *C)
* twice which can depgraph update the same object at once */
if (G.is_rendering == false) {
/* depsgraph gets called, might send more notifiers */
- ViewLayer *view_layer = CTX_data_view_layer(C);
Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ED_update_for_newframe(CTX_data_main(C), scene, view_layer, depsgraph);
+ ED_update_for_newframe(CTX_data_main(C), depsgraph);
}
}
}
@@ -610,14 +608,6 @@ int WM_operator_poll_context(bContext *C, wmOperatorType *ot, short context)
return wm_operator_call_internal(C, ot, NULL, NULL, context, true);
}
-static void wm_operator_print(bContext *C, wmOperator *op)
-{
- /* context is needed for enum function */
- char *buf = WM_operator_pystring(C, op, false, true);
- puts(buf);
- MEM_freeN(buf);
-}
-
/**
* Sets the active region for this space from the context.
*
@@ -778,10 +768,7 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, bool ca
}
if (retval & OPERATOR_FINISHED) {
- if (G.debug & G_DEBUG_WM) {
- /* todo - this print may double up, might want to check more flags then the FINISHED */
- wm_operator_print(C, op);
- }
+ CLOG_STR_INFO_N(WM_LOG_OPERATORS, 1, WM_operator_pystring(C, op, false, true));
if (caller_owns_reports == false) {
BKE_reports_print(op->reports, RPT_DEBUG); /* print out reports to console. */
@@ -1106,9 +1093,7 @@ bool WM_operator_last_properties_init(wmOperator *op)
IDProperty *replaceprops = IDP_New(IDP_GROUP, &val, "wmOperatorProperties");
PropertyRNA *iterprop;
- if (G.debug & G_DEBUG_WM) {
- printf("%s: loading previous properties for '%s'\n", __func__, op->type->idname);
- }
+ CLOG_INFO(WM_LOG_OPERATORS, 1, "loading previous properties for '%s'", op->type->idname);
iterprop = RNA_struct_iterator_property(op->type->srna);
@@ -1153,9 +1138,7 @@ bool WM_operator_last_properties_store(wmOperator *op)
}
if (op->properties) {
- if (G.debug & G_DEBUG_WM) {
- printf("%s: storing properties for '%s'\n", __func__, op->type->idname);
- }
+ CLOG_INFO(WM_LOG_OPERATORS, 1, "storing properties for '%s'", op->type->idname);
op->type->last_properties = IDP_CopyProperty(op->properties);
return true;
}
@@ -1205,11 +1188,12 @@ static int wm_operator_invoke(
WM_operator_last_properties_init(op);
}
- if ((G.debug & G_DEBUG_HANDLERS) && ((event == NULL) || (event->type != MOUSEMOVE))) {
- printf("%s: handle evt %d win %d op %s\n",
- __func__, event ? event->type : 0, CTX_wm_screen(C)->subwinactive, ot->idname);
+ if ((event == NULL) || (event->type != MOUSEMOVE)) {
+ CLOG_INFO(WM_LOG_HANDLERS, 2,
+ "handle evt %d win %p op %s",
+ event ? event->type : 0, CTX_wm_screen(C)->active_region, ot->idname);
}
-
+
if (op->type->invoke && event) {
wm_region_mouse_co(C, event);
@@ -1234,9 +1218,9 @@ static int wm_operator_invoke(
}
else {
/* debug, important to leave a while, should never happen */
- printf("%s: invalid operator call '%s'\n", __func__, ot->idname);
+ CLOG_ERROR(WM_LOG_OPERATORS, "invalid operator call '%s'", op->idname);
}
-
+
/* Note, if the report is given as an argument then assume the caller will deal with displaying them
* currently python only uses this */
if (!(retval & OPERATOR_HANDLED) && (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED))) {
@@ -1344,6 +1328,8 @@ static int wm_operator_call_internal(
switch (context) {
case WM_OP_INVOKE_DEFAULT:
case WM_OP_INVOKE_REGION_WIN:
+ case WM_OP_INVOKE_REGION_PREVIEW:
+ case WM_OP_INVOKE_REGION_CHANNELS:
case WM_OP_INVOKE_AREA:
case WM_OP_INVOKE_SCREEN:
/* window is needed for invoke, cancel operator */
@@ -1509,8 +1495,10 @@ int WM_operator_call_py(
if (is_undo && op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm)
wm->op_undo_depth--;
}
- else
- printf("error \"%s\" operator has no exec function, python cannot call it\n", op->type->name);
+ else {
+ CLOG_WARN(WM_LOG_OPERATORS, "\"%s\" operator has no exec function, Python cannot call it", op->type->name);
+ }
+
#endif
/* not especially nice using undo depth here, its used so py never
@@ -1554,8 +1542,9 @@ static void wm_handler_op_context(bContext *C, wmEventHandler *handler, const wm
if (sa == NULL) {
/* when changing screen layouts with running modal handlers (like render display), this
* is not an error to print */
- if (handler->op == NULL)
- printf("internal error: handler (%s) has invalid area\n", handler->op->type->idname);
+ if (handler->op == NULL) {
+ CLOG_ERROR(WM_LOG_HANDLERS, "internal error: handler (%s) has invalid area", handler->op->type->idname);
+ }
}
else {
ARegion *ar;
@@ -1901,10 +1890,9 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
//retval &= ~OPERATOR_PASS_THROUGH;
}
}
-
}
else {
- printf("%s: error '%s' missing modal\n", __func__, op->idname);
+ CLOG_ERROR(WM_LOG_HANDLERS, "missing modal '%s'", op->idname);
}
}
else {
@@ -2180,7 +2168,7 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
PRINT("%s: checking '%s' ...", __func__, keymap->idname);
- if (!keymap->poll || keymap->poll(C)) {
+ if (WM_keymap_poll(C, keymap)) {
PRINT("pass\n");
@@ -2195,19 +2183,15 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
action |= wm_handler_operator_call(C, handlers, handler, event, kmi->ptr);
if (action & WM_HANDLER_BREAK) {
/* not always_pass here, it denotes removed handler */
-
- if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS))
- printf("%s: handled! '%s'\n", __func__, kmi->idname);
-
+ CLOG_INFO(WM_LOG_HANDLERS, 2, "handled! '%s'", kmi->idname);
break;
}
else {
if (action & WM_HANDLER_HANDLED) {
- if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS))
- printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname);
+ CLOG_INFO(WM_LOG_HANDLERS, 2, "handled - and pass on! '%s'", kmi->idname);
}
else {
- PRINT("%s: un-handled '%s'\n", __func__, kmi->idname);
+ CLOG_INFO(WM_LOG_HANDLERS, 2, "un-handled '%s'", kmi->idname);
}
}
}
@@ -2466,10 +2450,8 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
{
event->val = KM_CLICK;
- if (G.debug & (G_DEBUG_HANDLERS)) {
- printf("%s: handling CLICK\n", __func__);
- }
-
+ CLOG_INFO(WM_LOG_HANDLERS, 1, "handling CLICK");
+
action |= wm_handlers_do_intern(C, event, handlers);
event->val = KM_RELEASE;
@@ -2680,9 +2662,8 @@ void wm_event_do_handlers(bContext *C)
int ncfra = time * (float)FPS + 0.5f;
if (ncfra != scene->r.cfra) {
scene->r.cfra = ncfra;
- ViewLayer *view_layer = CTX_data_view_layer(C);
Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ED_update_for_newframe(CTX_data_main(C), scene, view_layer, depsgraph);
+ ED_update_for_newframe(CTX_data_main(C), depsgraph);
WM_event_add_notifier(C, NC_WINDOW, NULL);
}
}
@@ -2708,8 +2689,8 @@ void wm_event_do_handlers(bContext *C)
/* take care of pie event filter */
if (wm_event_pie_filter(win, event)) {
- if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
- printf("\n%s: event filtered due to pie button pressed\n", __func__);
+ if (!ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ CLOG_INFO(WM_LOG_HANDLERS, 1, "event filtered due to pie button pressed");
}
BLI_remlink(&win->queue, event);
wm_event_free(event);
@@ -2764,7 +2745,7 @@ void wm_event_do_handlers(bContext *C)
/* Note: setting subwin active should be done here, after modal handlers have been done */
if (event->type == MOUSEMOVE) {
/* state variables in screen, cursors. Also used in wm_draw.c, fails for modal handlers though */
- ED_screen_set_subwinactive(C, event);
+ ED_screen_set_active_region(C, event);
/* for regions having custom cursors */
wm_paintcursor_test(C, event);
}
@@ -3058,7 +3039,7 @@ wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap
wmEventHandler *handler;
if (!keymap) {
- printf("%s: called with NULL keymap\n", __func__);
+ CLOG_WARN(WM_LOG_HANDLERS, "called with NULL keymap");
return NULL;
}
@@ -3226,7 +3207,7 @@ static void WM_event_remove_handler(ListBase *handlers, wmEventHandler *handler)
}
#endif
-void WM_event_add_mousemove(bContext *C)
+void WM_event_add_mousemove(const bContext *C)
{
wmWindow *window = CTX_wm_window(C);
@@ -3679,8 +3660,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
/* double click test */
if (wm_event_is_double_click(&event, evt)) {
- if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS))
- printf("%s Send double click\n", __func__);
+ CLOG_INFO(WM_LOG_HANDLERS, 1, "Send double click");
event.val = KM_DBL_CLICK;
}
if (event.val == KM_PRESS) {
@@ -3734,7 +3714,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
/* ghost should do this already for key up */
if (event.utf8_buf[0]) {
- printf("%s: ghost on your platform is misbehaving, utf8 events on key up!\n", __func__);
+ CLOG_ERROR(WM_LOG_EVENTS, "ghost on your platform is misbehaving, utf8 events on key up!");
}
event.utf8_buf[0] = '\0';
}
@@ -3747,8 +3727,9 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
if (event.utf8_buf[0]) {
if (BLI_str_utf8_size(event.utf8_buf) == -1) {
- printf("%s: ghost detected an invalid unicode character '%d'!\n",
- __func__, (int)(unsigned char)event.utf8_buf[0]);
+ CLOG_ERROR(WM_LOG_EVENTS,
+ "ghost detected an invalid unicode character '%d'",
+ (int)(unsigned char)event.utf8_buf[0]);
event.utf8_buf[0] = '\0';
}
}
@@ -3797,8 +3778,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
/* double click test */
/* if previous event was same type, and previous was release, and now it presses... */
if (wm_event_is_double_click(&event, evt)) {
- if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS))
- printf("%s Send double click\n", __func__);
+ CLOG_INFO(WM_LOG_HANDLERS, 1, "Send double click");
evt->val = event.val = KM_DBL_CLICK;
}
@@ -3868,9 +3848,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
attach_ndof_data(&event, customdata);
wm_event_add(win, &event);
- if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS))
- printf("%s sending NDOF_MOTION, prev = %d %d\n", __func__, event.x, event.y);
-
+ CLOG_INFO(WM_LOG_HANDLERS, 1, "sending NDOF_MOTION, prev = %d %d", event.x, event.y);
break;
}
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 6a86644da17..6591a8c9f59 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -62,6 +62,8 @@
#include "BLT_translation.h"
+#include "BLF_api.h"
+
#include "DNA_mesh_types.h" /* only for USE_BMESH_SAVE_AS_COMPAT */
#include "DNA_object_types.h"
#include "DNA_space_types.h"
@@ -85,10 +87,12 @@
#include "BKE_sound.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "BKE_undo_system.h"
#include "BKE_workspace.h"
#include "BLO_readfile.h"
#include "BLO_writefile.h"
+#include "BLO_undofile.h" /* to save from an undo memfile */
#include "RNA_access.h"
#include "RNA_define.h"
@@ -102,6 +106,7 @@
#include "ED_screen.h"
#include "ED_view3d.h"
#include "ED_util.h"
+#include "ED_undo.h"
#include "GHOST_C-api.h"
#include "GHOST_Path-api.h"
@@ -182,7 +187,7 @@ static void wm_window_match_init(bContext *C, ListBase *wmlist)
static void wm_window_substitute_old(wmWindowManager *wm, wmWindow *oldwin, wmWindow *win)
{
win->ghostwin = oldwin->ghostwin;
- win->multisamples = oldwin->multisamples;
+ win->gwnctx = oldwin->gwnctx;
win->active = oldwin->active;
if (win->active)
wm->winactive = win;
@@ -191,7 +196,7 @@ static void wm_window_substitute_old(wmWindowManager *wm, wmWindow *oldwin, wmWi
GHOST_SetWindowUserData(win->ghostwin, win); /* pointer back */
oldwin->ghostwin = NULL;
- oldwin->multisamples = 0;
+ oldwin->gwnctx = NULL;
win->eventstate = oldwin->eventstate;
oldwin->eventstate = NULL;
@@ -353,6 +358,8 @@ static void wm_init_userdef(Main *bmain, const bool read_userdef_from_memory)
/* update tempdir from user preferences */
BKE_tempdir_init(U.tempdir);
+
+ BLF_antialias_set((U.text_render & USER_TEXT_DISABLE_AA) == 0);
}
@@ -497,6 +504,8 @@ static void wm_file_read_post(bContext *C, const bool is_startup_file, const boo
BPY_python_reset(C);
addons_loaded = true;
}
+#else
+ UNUSED_VARS(use_userdef);
#endif /* WITH_PYTHON */
WM_operatortype_last_properties_clear_all();
@@ -528,9 +537,13 @@ static void wm_file_read_post(bContext *C, const bool is_startup_file, const boo
}
if (!G.background) {
-// undo_editmode_clear();
- BKE_undo_reset();
- BKE_undo_write(C, "original"); /* save current state */
+ if (wm->undo_stack == NULL) {
+ wm->undo_stack = BKE_undosys_stack_create();
+ }
+ else {
+ BKE_undosys_stack_clear(wm->undo_stack);
+ }
+ BKE_undosys_stack_init_from_main(wm->undo_stack, CTX_data_main(C));
}
}
@@ -1039,19 +1052,21 @@ static ImBuf *blend_file_thumb(const bContext *C, Scene *scene, ViewLayer *view_
}
/* gets scaled to BLEN_THUMB_SIZE */
+ RenderEngineType *engine_type = CTX_data_engine_type(C);
+
if (scene->camera) {
ibuf = ED_view3d_draw_offscreen_imbuf_simple(
- &eval_ctx, scene, view_layer, scene->camera,
+ &eval_ctx, scene, view_layer, engine_type, scene->camera,
BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
IB_rect, V3D_OFSDRAW_NONE, OB_SOLID, R_ALPHAPREMUL, 0, NULL,
- NULL, NULL, err_out);
+ NULL, err_out);
}
else {
ibuf = ED_view3d_draw_offscreen_imbuf(
- &eval_ctx, scene, view_layer, v3d, ar,
+ &eval_ctx, scene, view_layer, engine_type, v3d, ar,
BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
IB_rect, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL,
- NULL, NULL, err_out);
+ NULL, err_out);
}
if (ibuf) {
@@ -1281,7 +1296,10 @@ void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *UNUSED(w
if (U.uiflag & USER_GLOBALUNDO) {
/* fast save of last undobuffer, now with UI */
- BKE_undo_save_file(filepath);
+ struct MemFile *memfile = ED_undosys_stack_memfile_get_active(wm->undo_stack);
+ if (memfile) {
+ BLO_memfile_write_file(memfile, filepath);
+ }
}
else {
/* save as regular blend file */
@@ -1365,13 +1383,13 @@ void wm_open_init_use_scripts(wmOperator *op, bool use_prefs)
/** \} */
-void WM_file_tag_modified(const bContext *C)
+void WM_file_tag_modified(void)
{
- wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindowManager *wm = G.main->wm.first;
if (wm->file_saved) {
wm->file_saved = 0;
/* notifier that data changed, for save-over warning or header */
- WM_event_add_notifier(C, NC_WM | ND_DATACHANGED, NULL);
+ WM_main_add_notifier(NC_WM | ND_DATACHANGED, NULL);
}
}
@@ -2125,6 +2143,10 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_WM | ND_FILESAVE, NULL);
+ if (RNA_boolean_get(op->ptr, "exit")) {
+ wm_exit_schedule_delayed(C);
+ }
+
return OPERATOR_FINISHED;
}
@@ -2196,11 +2218,13 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *U
char path[FILE_MAX];
RNA_string_get(op->ptr, "filepath", path);
- if (BLI_exists(path)) {
+ if (RNA_boolean_get(op->ptr, "check_existing") && BLI_exists(path)) {
ret = WM_operator_confirm_message_ex(C, op, IFACE_("Save Over?"), ICON_QUESTION, path);
}
else {
ret = wm_save_as_mainfile_exec(C, op);
+ /* Without this there is no feedback the file was saved. */
+ BKE_reportf(op->reports, RPT_INFO, "Saved \"%s\"", BLI_path_basename(path));
}
}
else {
@@ -2222,12 +2246,16 @@ void WM_OT_save_mainfile(wmOperatorType *ot)
ot->check = blend_save_check;
/* omit window poll so this can work in background mode */
+ PropertyRNA *prop;
WM_operator_properties_filesel(
ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_SAVE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
RNA_def_boolean(ot->srna, "compress", false, "Compress", "Write compressed .blend file");
RNA_def_boolean(ot->srna, "relative_remap", false, "Remap Relative",
"Remap relative paths when saving in a different directory");
+
+ prop = RNA_def_boolean(ot->srna, "exit", false, "Exit", "Exit Blender after saving");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index cd6a38cb9a8..a33df1bc1f2 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -320,9 +320,6 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
char path[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX_LIBEXTRA], relname[FILE_MAX];
char *group, *name;
int totfiles = 0;
- short flag;
- bool has_item = false;
- bool do_append;
RNA_string_get(op->ptr, "filename", relname);
RNA_string_get(op->ptr, "directory", root);
@@ -359,8 +356,8 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- flag = wm_link_append_flag(op);
- do_append = (flag & FILE_LINK) == 0;
+ short flag = wm_link_append_flag(op);
+ const bool do_append = (flag & FILE_LINK) == 0;
/* sanity checks for flag */
if (scene && scene->id.lib) {
@@ -406,7 +403,6 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
BLI_ghash_insert(libraries, BLI_strdup(libname), SET_INT_IN_POINTER(lib_idx));
lib_idx++;
wm_link_append_data_library_add(lapp_data, libname);
- has_item = true;
}
}
}
@@ -429,7 +425,6 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
item = wm_link_append_data_item_add(lapp_data, name, BKE_idcode_from_name(group), NULL);
BLI_BITMAP_ENABLE(item->libraries, lib_idx);
- has_item = true;
}
}
RNA_END;
@@ -442,10 +437,10 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
wm_link_append_data_library_add(lapp_data, libname);
item = wm_link_append_data_item_add(lapp_data, name, BKE_idcode_from_name(group), NULL);
BLI_BITMAP_ENABLE(item->libraries, 0);
- has_item = true;
}
- if (!has_item) {
+ if (lapp_data->num_items == 0) {
+ /* Early out in case there is nothing to link. */
wm_link_append_data_free(lapp_data);
return OPERATOR_CANCELLED;
}
@@ -614,7 +609,6 @@ static void lib_relocate_do(
LinkNode *itemlink;
int item_idx;
- bool has_item = false;
/* Remove all IDs to be reloaded from Main. */
lba_idx = set_listbasepointers(bmain, lbarray);
@@ -636,7 +630,6 @@ static void lib_relocate_do(
BLI_remlink(lbarray[lba_idx], id);
item = wm_link_append_data_item_add(lapp_data, id->name + 2, idcode, id);
BLI_BITMAP_SET_ALL(item->libraries, true, lapp_data->num_libraries);
- has_item = true;
#ifdef PRINT_DEBUG
printf("\tdatablock to seek for: %s\n", id->name);
@@ -645,8 +638,8 @@ static void lib_relocate_do(
}
}
- if (!has_item) {
- /* nothing to relocate */
+ if (lapp_data->num_items == 0) {
+ /* Early out in case there is nothing to do. */
return;
}
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index fa5fd38b7b2..6da9101156a 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -41,7 +41,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_lasso.h"
+#include "BLI_lasso_2d.h"
#include "BKE_context.h"
@@ -49,7 +49,6 @@
#include "WM_types.h"
#include "wm.h"
-#include "wm_subwindow.h"
#include "wm_draw.h"
#include "GPU_immediate.h"
@@ -64,40 +63,37 @@ wmGesture *WM_gesture_new(bContext *C, const wmEvent *event, int type)
wmGesture *gesture = MEM_callocN(sizeof(wmGesture), "new gesture");
wmWindow *window = CTX_wm_window(C);
ARegion *ar = CTX_wm_region(C);
- int sx, sy;
BLI_addtail(&window->gesture, gesture);
gesture->type = type;
gesture->event_type = event->type;
- gesture->swinid = ar->swinid; /* means only in area-region context! */
+ gesture->winrct = ar->winrct;
gesture->userdata_free = true; /* Free if userdata is set. */
gesture->modal_state = GESTURE_MODAL_NOP;
- wm_subwindow_origin_get(window, gesture->swinid, &sx, &sy);
-
if (ELEM(type, WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT, WM_GESTURE_TWEAK,
WM_GESTURE_CIRCLE, WM_GESTURE_STRAIGHTLINE))
{
rcti *rect = MEM_callocN(sizeof(rcti), "gesture rect new");
gesture->customdata = rect;
- rect->xmin = event->x - sx;
- rect->ymin = event->y - sy;
+ rect->xmin = event->x - gesture->winrct.xmin;
+ rect->ymin = event->y - gesture->winrct.ymin;
if (type == WM_GESTURE_CIRCLE) {
/* caller is responsible for initializing 'xmax' to radius. */
}
else {
- rect->xmax = event->x - sx;
- rect->ymax = event->y - sy;
+ rect->xmax = event->x - gesture->winrct.xmin;
+ rect->ymax = event->y - gesture->winrct.ymin;
}
}
else if (ELEM(type, WM_GESTURE_LINES, WM_GESTURE_LASSO)) {
short *lasso;
gesture->points_alloc = 1024;
gesture->customdata = lasso = MEM_mallocN(sizeof(short[2]) * gesture->points_alloc, "lasso points");
- lasso[0] = event->x - sx;
- lasso[1] = event->y - sy;
+ lasso[0] = event->x - gesture->winrct.xmin;
+ lasso[1] = event->y - gesture->winrct.ymin;
gesture->points = 1;
}
@@ -273,14 +269,13 @@ static void draw_filled_lasso_px_cb(int x, int x_end, int y, void *user_data)
memset(col, 0x10, x_end - x);
}
-static void draw_filled_lasso(wmWindow *win, wmGesture *gt)
+static void draw_filled_lasso(wmGesture *gt)
{
const short *lasso = (short *)gt->customdata;
const int tot = gt->points;
int (*moves)[2] = MEM_mallocN(sizeof(*moves) * (tot + 1), __func__);
int i;
rcti rect;
- rcti rect_win;
float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
for (i = 0; i < tot; i++, lasso += 2) {
@@ -290,10 +285,9 @@ static void draw_filled_lasso(wmWindow *win, wmGesture *gt)
BLI_lasso_boundbox(&rect, (const int (*)[2])moves, tot);
- wm_subwindow_rect_get(win, gt->swinid, &rect_win);
- BLI_rcti_translate(&rect, rect_win.xmin, rect_win.ymin);
- BLI_rcti_isect(&rect_win, &rect, &rect);
- BLI_rcti_translate(&rect, -rect_win.xmin, -rect_win.ymin);
+ BLI_rcti_translate(&rect, gt->winrct.xmin, gt->winrct.ymin);
+ BLI_rcti_isect(&gt->winrct, &rect, &rect);
+ BLI_rcti_translate(&rect, -gt->winrct.xmin, -gt->winrct.ymin);
/* highly unlikely this will fail, but could crash if (tot == 0) */
if (BLI_rcti_is_empty(&rect) == false) {
@@ -335,13 +329,13 @@ static void draw_filled_lasso(wmWindow *win, wmGesture *gt)
}
-static void wm_gesture_draw_lasso(wmWindow *win, wmGesture *gt, bool filled)
+static void wm_gesture_draw_lasso(wmGesture *gt, bool filled)
{
const short *lasso = (short *)gt->customdata;
int i;
if (filled) {
- draw_filled_lasso(win, gt);
+ draw_filled_lasso(gt);
}
const int numverts = gt->points;
@@ -425,7 +419,7 @@ void wm_gesture_draw(wmWindow *win)
glLineWidth(1.0f);
for (; gt; gt = gt->next) {
/* all in subwindow space */
- wmSubWindowSet(win, gt->swinid);
+ wmViewport(&gt->winrct);
if (gt->type == WM_GESTURE_RECT)
wm_gesture_draw_rect(gt);
@@ -442,9 +436,9 @@ void wm_gesture_draw(wmWindow *win)
}
}
else if (gt->type == WM_GESTURE_LINES)
- wm_gesture_draw_lasso(win, gt, false);
+ wm_gesture_draw_lasso(gt, false);
else if (gt->type == WM_GESTURE_LASSO)
- wm_gesture_draw_lasso(win, gt, true);
+ wm_gesture_draw_lasso(gt, true);
else if (gt->type == WM_GESTURE_STRAIGHTLINE)
wm_gesture_draw_line(gt);
}
diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c
index a554727cacd..01184f47920 100644
--- a/source/blender/windowmanager/intern/wm_gesture_ops.c
+++ b/source/blender/windowmanager/intern/wm_gesture_ops.c
@@ -47,7 +47,6 @@
#include "wm.h"
#include "wm_event_types.h"
#include "wm_event_system.h"
-#include "wm_subwindow.h"
#include "ED_screen.h"
@@ -198,18 +197,15 @@ int WM_gesture_border_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmGesture *gesture = op->customdata;
rcti *rect = gesture->customdata;
- int sx, sy;
if (event->type == MOUSEMOVE) {
- wm_subwindow_origin_get(CTX_wm_window(C), gesture->swinid, &sx, &sy);
-
if (gesture->type == WM_GESTURE_CROSS_RECT && gesture->is_active == false) {
- rect->xmin = rect->xmax = event->x - sx;
- rect->ymin = rect->ymax = event->y - sy;
+ rect->xmin = rect->xmax = event->x - gesture->winrct.xmin;
+ rect->ymin = rect->ymax = event->y - gesture->winrct.ymin;
}
else {
- rect->xmax = event->x - sx;
- rect->ymax = event->y - sy;
+ rect->xmax = event->x - gesture->winrct.xmin;
+ rect->ymax = event->y - gesture->winrct.ymin;
}
gesture_border_apply_rect(op);
@@ -333,13 +329,11 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmGesture *gesture = op->customdata;
rcti *rect = gesture->customdata;
- int sx, sy;
if (event->type == MOUSEMOVE) {
- wm_subwindow_origin_get(CTX_wm_window(C), gesture->swinid, &sx, &sy);
- rect->xmin = event->x - sx;
- rect->ymin = event->y - sy;
+ rect->xmin = event->x - gesture->winrct.xmin;
+ rect->ymin = event->y - gesture->winrct.ymin;
wm_gesture_tag_redraw(C);
@@ -464,24 +458,22 @@ static void gesture_tweak_modal(bContext *C, const wmEvent *event)
wmWindow *window = CTX_wm_window(C);
wmGesture *gesture = window->tweak;
rcti *rect = gesture->customdata;
- int sx, sy, val;
+ int val;
switch (event->type) {
case MOUSEMOVE:
case INBETWEEN_MOUSEMOVE:
- wm_subwindow_origin_get(window, gesture->swinid, &sx, &sy);
-
- rect->xmax = event->x - sx;
- rect->ymax = event->y - sy;
+ rect->xmax = event->x - gesture->winrct.xmin;
+ rect->ymax = event->y - gesture->winrct.ymin;
if ((val = wm_gesture_evaluate(gesture))) {
wmEvent tevent;
wm_event_init_from_window(window, &tevent);
/* We want to get coord from start of drag, not from point where it becomes a tweak event, see T40549 */
- tevent.x = rect->xmin + sx;
- tevent.y = rect->ymin + sy;
+ tevent.x = rect->xmin + gesture->winrct.xmin;
+ tevent.y = rect->ymin + gesture->winrct.ymin;
if (gesture->event_type == LEFTMOUSE)
tevent.type = EVT_TWEAK_L;
else if (gesture->event_type == RIGHTMOUSE)
@@ -617,7 +609,6 @@ static void gesture_lasso_apply(bContext *C, wmOperator *op)
int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmGesture *gesture = op->customdata;
- int sx, sy;
switch (event->type) {
case MOUSEMOVE:
@@ -625,8 +616,6 @@ int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event)
wm_gesture_tag_redraw(C);
- wm_subwindow_origin_get(CTX_wm_window(C), gesture->swinid, &sx, &sy);
-
if (gesture->points == gesture->points_alloc) {
gesture->points_alloc *= 2;
gesture->customdata = MEM_reallocN(gesture->customdata, sizeof(short[2]) * gesture->points_alloc);
@@ -637,15 +626,15 @@ int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event)
short *lasso = gesture->customdata;
lasso += (2 * gesture->points - 2);
- x = (event->x - sx - lasso[0]);
- y = (event->y - sy - lasso[1]);
+ x = (event->x - gesture->winrct.xmin - lasso[0]);
+ y = (event->y - gesture->winrct.ymin - lasso[1]);
/* make a simple distance check to get a smoother lasso
* add only when at least 2 pixels between this and previous location */
if ((x * x + y * y) > 4) {
lasso += 2;
- lasso[0] = event->x - sx;
- lasso[1] = event->y - sy;
+ lasso[0] = event->x - gesture->winrct.xmin;
+ lasso[1] = event->y - gesture->winrct.ymin;
gesture->points++;
}
}
@@ -813,18 +802,15 @@ int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *ev
{
wmGesture *gesture = op->customdata;
rcti *rect = gesture->customdata;
- int sx, sy;
if (event->type == MOUSEMOVE) {
- wm_subwindow_origin_get(CTX_wm_window(C), gesture->swinid, &sx, &sy);
-
if (gesture->is_active == false) {
- rect->xmin = rect->xmax = event->x - sx;
- rect->ymin = rect->ymax = event->y - sy;
+ rect->xmin = rect->xmax = event->x - gesture->winrct.xmin;
+ rect->ymin = rect->ymax = event->y - gesture->winrct.ymin;
}
else {
- rect->xmax = event->x - sx;
- rect->ymax = event->y - sy;
+ rect->xmax = event->x - gesture->winrct.xmin;
+ rect->ymax = event->y - gesture->winrct.ymin;
gesture_straightline_apply(C, op);
}
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 55ed8b2a091..4c7c2cc96e4 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -40,6 +40,8 @@
#include "MEM_guardedalloc.h"
+#include "CLG_log.h"
+
#include "DNA_genfile.h"
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
@@ -53,6 +55,7 @@
#include "BLI_utildefines.h"
#include "BLO_writefile.h"
+#include "BLO_undofile.h"
#include "BKE_blender.h"
#include "BKE_blender_undo.h"
@@ -111,11 +114,13 @@
#include "ED_space_api.h"
#include "ED_screen.h"
#include "ED_util.h"
+#include "ED_undo.h"
#include "UI_interface.h"
#include "BLF_api.h"
#include "BLT_lang.h"
+#include "GPU_material.h"
#include "GPU_buffers.h"
#include "GPU_draw.h"
#include "GPU_init_exit.h"
@@ -125,10 +130,17 @@
#include "DEG_depsgraph.h"
+#include "DRW_engine.h"
+
#ifdef WITH_OPENSUBDIV
# include "BKE_subsurf.h"
#endif
+CLG_LOGREF_DECLARE_GLOBAL(WM_LOG_OPERATORS, "wm.operator");
+CLG_LOGREF_DECLARE_GLOBAL(WM_LOG_HANDLERS, "wm.handler");
+CLG_LOGREF_DECLARE_GLOBAL(WM_LOG_EVENTS, "wm.event");
+CLG_LOGREF_DECLARE_GLOBAL(WM_LOG_KEYMAPS, "wm.keymap");
+
static void wm_init_reports(bContext *C)
{
ReportList *reports = CTX_wm_reports(C);
@@ -144,11 +156,6 @@ static void wm_free_reports(bContext *C)
BKE_reports_clear(reports);
}
-static void wm_undo_kill_callback(bContext *C)
-{
- WM_jobs_kill_all_except(CTX_wm_manager(C), CTX_wm_screen(C));
-}
-
bool wm_start_with_console = false; /* used in creator.c */
/* only called once, for startup */
@@ -169,7 +176,7 @@ void WM_init(bContext *C, int argc, const char **argv)
wm_manipulatortype_init();
wm_manipulatorgrouptype_init();
- BKE_undo_callback_wm_kill_jobs_set(wm_undo_kill_callback);
+ ED_undosys_type_init();
BKE_library_callback_free_window_manager_set(wm_close_and_free); /* library.c */
BKE_library_callback_free_notifier_reference_set(WM_main_remove_notifier_reference); /* library.c */
@@ -207,6 +214,7 @@ void WM_init(bContext *C, int argc, const char **argv)
/* sets 3D mouse deadzone */
WM_ndof_deadzone_set(U.ndof_deadzone);
#endif
+ DRW_opengl_context_create();
GPU_init();
@@ -256,7 +264,7 @@ void WM_init(bContext *C, int argc, const char **argv)
clear_matcopybuf();
ED_render_clear_mtex_copybuf();
- // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ // glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
wm_history_file_read();
@@ -441,6 +449,29 @@ static void wait_for_console_key(void)
}
#endif
+static int wm_exit_handler(bContext *C, const wmEvent *event, void *userdata)
+{
+ WM_exit(C);
+
+ UNUSED_VARS(event, userdata);
+ return WM_UI_HANDLER_BREAK;
+}
+
+/**
+ * Cause a delayed WM_exit() call to avoid leaking memory when trying to exit from within operators.
+ */
+void wm_exit_schedule_delayed(const bContext *C)
+{
+ /* What we do here is a little bit hacky, but quite simple and doesn't require bigger
+ * changes: Add a handler wrapping WM_exit() to cause a delayed call of it. */
+
+ wmWindow *win = CTX_wm_window(C);
+
+ /* Use modal UI handler for now. Could add separate WM handlers or so, but probably not worth it. */
+ WM_event_add_ui_handler(C, &win->modalhandlers, wm_exit_handler, NULL, NULL, 0);
+ WM_event_add_mousemove(C); /* ensure handler actually gets called */
+}
+
/**
* \note doesn't run exit() call #WM_exit() for that.
*/
@@ -455,7 +486,8 @@ void WM_exit_ext(bContext *C, const bool do_python)
wmWindow *win;
if (!G.background) {
- if ((U.uiflag2 & USER_KEEP_SESSION) || BKE_undo_is_valid(NULL)) {
+ struct MemFile *undo_memfile = wm->undo_stack ? ED_undosys_stack_memfile_get_active(wm->undo_stack) : NULL;
+ if ((U.uiflag2 & USER_KEEP_SESSION) || (undo_memfile != NULL)) {
/* save the undo state as quit.blend */
char filename[FILE_MAX];
bool has_edited;
@@ -466,7 +498,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
has_edited = ED_editors_flush_edits(C, false);
if ((has_edited && BLO_write_file(CTX_data_main(C), filename, fileflags, NULL, NULL)) ||
- BKE_undo_save_file(filename))
+ (undo_memfile && BLO_memfile_write_file(undo_memfile, filename)))
{
printf("Saved session recovery to '%s'\n", filename);
}
@@ -489,11 +521,13 @@ void WM_exit_ext(bContext *C, const bool do_python)
wm_dropbox_free();
WM_menutype_free();
WM_uilisttype_free();
-
+
/* all non-screen and non-space stuff editors did, like editmode */
if (C)
ED_editors_exit(C);
+ ED_undosys_type_free();
+
// XXX
// BIF_GlobalReebFree();
// BIF_freeRetarget();
@@ -520,6 +554,17 @@ void WM_exit_ext(bContext *C, const bool do_python)
#ifdef WITH_COMPOSITOR
COM_deinitialize();
#endif
+
+ if (!G.background) {
+#ifdef WITH_OPENSUBDIV
+ BKE_subsurf_osd_cleanup();
+#endif
+
+ GPU_global_buffer_pool_free();
+ GPU_free_unused_buffers();
+
+ GPU_exit();
+ }
BKE_blender_free(); /* blender.c, does entire library and spacetypes */
// free_matcopybuf();
@@ -538,6 +583,11 @@ void WM_exit_ext(bContext *C, const bool do_python)
BLF_exit();
+ if (!G.background) {
+ GPU_pass_cache_free();
+ DRW_opengl_context_destroy();
+ }
+
#ifdef WITH_INTERNATIONAL
BLF_free_unifont();
BLF_free_unifont_mono();
@@ -565,19 +615,6 @@ void WM_exit_ext(bContext *C, const bool do_python)
(void)do_python;
#endif
- if (!G.background) {
-#ifdef WITH_OPENSUBDIV
- BKE_subsurf_osd_cleanup();
-#endif
-
- GPU_global_buffer_pool_free();
- GPU_free_unused_buffers();
-
- GPU_exit();
- }
-
- BKE_undo_reset();
-
ED_file_exit(); /* for fsmenu */
UI_exit();
@@ -602,6 +639,8 @@ void WM_exit_ext(bContext *C, const bool do_python)
* see also T50676. */
BKE_sound_exit();
+ CLG_exit();
+
BKE_blender_atexit();
if (MEM_get_memory_blocks_in_use() != 0) {
@@ -616,6 +655,10 @@ void WM_exit_ext(bContext *C, const bool do_python)
BKE_tempdir_session_purge();
}
+/**
+ * \brief Main exit function to close Blender ordinarily.
+ * \note Use #wm_exit_schedule_delayed() to close Blender from an operator. Might leak memory otherwise.
+ */
void WM_exit(bContext *C)
{
WM_exit_ext(C, 1);
diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c
index 528b9e2b3d9..f9fe787ed2d 100644
--- a/source/blender/windowmanager/intern/wm_jobs.c
+++ b/source/blender/windowmanager/intern/wm_jobs.c
@@ -418,8 +418,8 @@ void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
// printf("job started: %s\n", wm_job->name);
- BLI_init_threads(&wm_job->threads, do_job_thread, 1);
- BLI_insert_thread(&wm_job->threads, wm_job);
+ BLI_threadpool_init(&wm_job->threads, do_job_thread, 1);
+ BLI_threadpool_insert(&wm_job->threads, wm_job);
}
/* restarted job has timer already */
@@ -450,7 +450,7 @@ static void wm_jobs_kill_job(wmWindowManager *wm, wmJob *wm_job)
wm_job->stop = true;
WM_job_main_thread_lock_release(wm_job);
- BLI_end_threads(&wm_job->threads);
+ BLI_threadpool_end(&wm_job->threads);
WM_job_main_thread_lock_acquire(wm_job);
if (wm_job->endjob)
@@ -601,7 +601,7 @@ void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
wm_job->running = false;
WM_job_main_thread_lock_release(wm_job);
- BLI_end_threads(&wm_job->threads);
+ BLI_threadpool_end(&wm_job->threads);
WM_job_main_thread_lock_acquire(wm_job);
if (wm_job->endnote)
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index 58e2110334b..6f42de73e61 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -1,4 +1,5 @@
/*
+ *
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -37,8 +38,10 @@
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
#include "MEM_guardedalloc.h"
+#include "CLG_log.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -49,6 +52,7 @@
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_screen.h"
+#include "BKE_workspace.h"
#include "BLT_translation.h"
@@ -341,6 +345,12 @@ static wmKeyMap *wm_keymap_new(const char *idname, int spaceid, int regionid)
km->spaceid = spaceid;
km->regionid = regionid;
+ {
+ const char *owner_id = RNA_struct_state_owner_get();
+ if (owner_id) {
+ BLI_strncpy(km->owner_id, owner_id, sizeof(km->owner_id));
+ }
+ }
return km;
}
@@ -398,6 +408,23 @@ bool WM_keymap_remove(wmKeyConfig *keyconf, wmKeyMap *keymap)
}
}
+
+bool WM_keymap_poll(bContext *C, wmKeyMap *keymap)
+{
+ /* If we're tagged, only use compatible. */
+ if (keymap->owner_id[0] != '\0') {
+ const WorkSpace *workspace = CTX_wm_workspace(C);
+ if (BKE_workspace_owner_id_check(workspace, keymap->owner_id) == false) {
+ return false;
+ }
+ }
+
+ if (keymap->poll != NULL) {
+ return keymap->poll(C);
+ }
+ return true;
+}
+
static void keymap_event_set(wmKeyMapItem *kmi, short type, short val, int modifier, short keymodifier)
{
kmi->type = type;
@@ -877,11 +904,13 @@ wmKeyMapItem *WM_modalkeymap_find_propvalue(wmKeyMap *km, const int propvalue)
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
{
wmOperatorType *ot = WM_operatortype_find(opname, 0);
-
- if (ot)
+
+ if (ot) {
ot->modalkeymap = km;
- else
- printf("error: modalkeymap_assign, unknown operator %s\n", opname);
+ }
+ else {
+ CLOG_ERROR(WM_LOG_KEYMAPS, "unknown operator '%s'", opname);
+ }
}
static void wm_user_modal_keymap_set_items(wmWindowManager *wm, wmKeyMap *km)
@@ -1087,7 +1116,7 @@ static wmKeyMapItem *wm_keymap_item_find_handlers(
for (handler = handlers->first; handler; handler = handler->next) {
keymap = WM_keymap_active(wm, handler->keymap);
- if (keymap && (!keymap->poll || keymap->poll((bContext *)C))) {
+ if (keymap && WM_keymap_poll((bContext *)C, keymap)) {
for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
/* skip disabled keymap items [T38447] */
if (kmi->flag & KMI_INACTIVE)
@@ -1719,7 +1748,7 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
km = WM_keymap_find_all(C, "Mesh", 0, 0);
/* some mesh operators are active in object mode too, like add-prim */
- if (km && km->poll && km->poll((bContext *)C) == 0) {
+ if (km && !WM_keymap_poll((bContext *)C, km)) {
km = WM_keymap_find_all(C, "Object Mode", 0, 0);
}
}
@@ -1729,7 +1758,7 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
km = WM_keymap_find_all(C, "Curve", 0, 0);
/* some curve operators are active in object mode too, like add-prim */
- if (km && km->poll && km->poll((bContext *)C) == 0) {
+ if (km && !WM_keymap_poll((bContext *)C, km)) {
km = WM_keymap_find_all(C, "Object Mode", 0, 0);
}
}
@@ -1757,7 +1786,7 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
km = WM_keymap_find_all(C, "Metaball", 0, 0);
/* some mball operators are active in object mode too, like add-prim */
- if (km && km->poll && km->poll((bContext *)C) == 0) {
+ if (km && !WM_keymap_poll((bContext *)C, km)) {
km = WM_keymap_find_all(C, "Object Mode", 0, 0);
}
}
@@ -1812,7 +1841,7 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
* Mesh keymap is probably not ideal, but best place I could find to put those. */
if (sl->spacetype == SPACE_VIEW3D) {
km = WM_keymap_find_all(C, "Mesh", 0, 0);
- if (km && km->poll && !km->poll((bContext *)C)) {
+ if (km && !WM_keymap_poll((bContext *)C, km)) {
km = NULL;
}
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 7637d222913..9679a55bc7a 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -46,6 +46,8 @@
#include "MEM_guardedalloc.h"
+#include "CLG_log.h"
+
#include "DNA_ID.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
@@ -59,7 +61,7 @@
#include "PIL_time.h"
#include "BLI_blenlib.h"
-#include "BLI_dial.h"
+#include "BLI_dial_2d.h"
#include "BLI_dynstr.h" /*for WM_operator_pystring */
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -97,7 +99,7 @@
#include "ED_numinput.h"
#include "ED_screen.h"
-#include "ED_util.h"
+#include "ED_undo.h"
#include "ED_view3d.h"
#include "RNA_access.h"
@@ -142,12 +144,12 @@ wmOperatorType *WM_operatortype_find(const char *idname, bool quiet)
}
if (!quiet) {
- printf("search for unknown operator '%s', '%s'\n", idname_bl, idname);
+ CLOG_INFO(WM_LOG_OPERATORS, 0, "search for unknown operator '%s', '%s'\n", idname_bl, idname);
}
}
else {
if (!quiet) {
- printf("search for empty operator\n");
+ CLOG_INFO(WM_LOG_OPERATORS, 0, "search for empty operator");
}
}
@@ -180,8 +182,7 @@ static wmOperatorType *wm_operatortype_append__begin(void)
static void wm_operatortype_append__end(wmOperatorType *ot)
{
if (ot->name == NULL) {
- fprintf(stderr, "ERROR: Operator %s has no name property!\n", ot->idname);
- ot->name = N_("Dummy Name");
+ CLOG_ERROR(WM_LOG_OPERATORS, "Operator '%s' has no name property", ot->idname);
}
/* Allow calling _begin without _end in operatortype creation. */
@@ -269,7 +270,7 @@ static int wm_macro_exec(bContext *C, wmOperator *op)
}
}
else {
- printf("%s: '%s' cant exec macro\n", __func__, opm->type->idname);
+ CLOG_WARN(WM_LOG_OPERATORS, "'%s' cant exec macro", opm->type->idname);
}
}
@@ -314,8 +315,9 @@ static int wm_macro_modal(bContext *C, wmOperator *op, const wmEvent *event)
wmOperator *opm = op->opm;
int retval = OPERATOR_FINISHED;
- if (opm == NULL)
- printf("%s: macro error, calling NULL modal()\n", __func__);
+ if (opm == NULL) {
+ CLOG_ERROR(WM_LOG_OPERATORS, "macro error, calling NULL modal()");
+ }
else {
retval = opm->type->modal(C, opm, event);
OPERATOR_RETVAL_CHECK(retval);
@@ -389,7 +391,7 @@ wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *nam
const char *i18n_context;
if (WM_operatortype_find(idname, true)) {
- printf("%s: macro error: operator %s exists\n", __func__, idname);
+ CLOG_ERROR(WM_LOG_OPERATORS, "operator %s exists, cannot create macro", idname);
return NULL;
}
@@ -1198,11 +1200,14 @@ int WM_menu_invoke_ex(bContext *C, wmOperator *op, int opcontext)
uiLayout *layout;
if (prop == NULL) {
- printf("%s: %s has no enum property set\n", __func__, op->type->idname);
+ CLOG_ERROR(WM_LOG_OPERATORS,
+ "'%s' has no enum property set",
+ op->type->idname);
}
else if (RNA_property_type(prop) != PROP_ENUM) {
- printf("%s: %s \"%s\" is not an enum property\n",
- __func__, op->type->idname, RNA_property_identifier(prop));
+ CLOG_ERROR(WM_LOG_OPERATORS,
+ "'%s', '%s' is not an enum property",
+ op->type->idname, RNA_property_identifier(prop));
}
else if (RNA_property_is_set(op->ptr, prop)) {
const int retval = op->type->exec(C, op);
@@ -1814,7 +1819,7 @@ static int wm_operator_tool_set_exec(bContext *C, wmOperator *op)
{
ScrArea *sa = CTX_wm_area(C);
- bToolDef tool_def = {0};
+ bToolDef tool_def = {{0}};
tool_def.index = RNA_int_get(op->ptr, "index");
tool_def.spacetype = sa->spacetype;
@@ -1956,8 +1961,9 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
memcpy(ibuf->rect, ibuf_template->rect, ibuf_template->x * ibuf_template->y * sizeof(char[4]));
}
else {
- printf("Splash expected %dx%d found %dx%d, ignoring: %s\n",
- x_expect, y_expect, ibuf_template->x, ibuf_template->y, splash_filepath);
+ CLOG_ERROR(WM_LOG_OPERATORS,
+ "Splash expected %dx%d found %dx%d, ignoring: %s\n",
+ x_expect, y_expect, ibuf_template->x, ibuf_template->y, splash_filepath);
}
IMB_freeImBuf(ibuf_template);
}
@@ -2315,22 +2321,29 @@ static void WM_OT_window_fullscreen_toggle(wmOperatorType *ot)
ot->poll = WM_operator_winactive;
}
-static int wm_exit_blender_exec(bContext *C, wmOperator *op)
+static int wm_exit_blender_exec(bContext *C, wmOperator *UNUSED(op))
{
- WM_operator_free(op);
-
- WM_exit(C);
-
+ wm_quit_with_optional_confirmation_prompt(C, CTX_wm_window(C));
return OPERATOR_FINISHED;
}
+static int wm_exit_blender_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ if (U.uiflag & USER_QUIT_PROMPT) {
+ return wm_exit_blender_exec(C, op);
+ }
+ else {
+ return WM_operator_confirm(C, op, event);
+ }
+}
+
static void WM_OT_quit_blender(wmOperatorType *ot)
{
ot->name = "Quit Blender";
ot->idname = "WM_OT_quit_blender";
ot->description = "Quit Blender";
- ot->invoke = WM_operator_confirm;
+ ot->invoke = wm_exit_blender_invoke;
ot->exec = wm_exit_blender_exec;
}
@@ -2508,6 +2521,7 @@ static void radial_control_set_tex(RadialControl *rc)
glBindTexture(GL_TEXTURE_2D, rc->gltex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, ibuf->x, ibuf->y, 0,
GL_RED, GL_FLOAT, ibuf->rect_float);
+ glBindTexture(GL_TEXTURE_2D, 0);
MEM_freeN(ibuf->rect_float);
MEM_freeN(ibuf);
}
@@ -2548,6 +2562,7 @@ static void radial_control_paint_tex(RadialControl *rc, float radius, float alph
unsigned int texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, rc->gltex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -2559,7 +2574,7 @@ static void radial_control_paint_tex(RadialControl *rc, float radius, float alph
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR);
immUniformColor3fvAlpha(col, alpha);
- immUniform1i("image", GL_TEXTURE0);
+ immUniform1i("image", 0);
/* set up rotation if available */
if (rc->rot_prop) {
@@ -3218,26 +3233,38 @@ static void WM_OT_radial_control(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
/* all paths relative to the context */
- RNA_def_string(ot->srna, "data_path_primary", NULL, 0, "Primary Data Path", "Primary path of property to be set by the radial control");
+ PropertyRNA *prop;
+ prop = RNA_def_string(ot->srna, "data_path_primary", NULL, 0, "Primary Data Path", "Primary path of property to be set by the radial control");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- RNA_def_string(ot->srna, "data_path_secondary", NULL, 0, "Secondary Data Path", "Secondary path of property to be set by the radial control");
+ prop = RNA_def_string(ot->srna, "data_path_secondary", NULL, 0, "Secondary Data Path", "Secondary path of property to be set by the radial control");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- RNA_def_string(ot->srna, "use_secondary", NULL, 0, "Use Secondary", "Path of property to select between the primary and secondary data paths");
+ prop = RNA_def_string(ot->srna, "use_secondary", NULL, 0, "Use Secondary", "Path of property to select between the primary and secondary data paths");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- RNA_def_string(ot->srna, "rotation_path", NULL, 0, "Rotation Path", "Path of property used to rotate the texture display");
+ prop = RNA_def_string(ot->srna, "rotation_path", NULL, 0, "Rotation Path", "Path of property used to rotate the texture display");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- RNA_def_string(ot->srna, "color_path", NULL, 0, "Color Path", "Path of property used to set the color of the control");
+ prop = RNA_def_string(ot->srna, "color_path", NULL, 0, "Color Path", "Path of property used to set the color of the control");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- RNA_def_string(ot->srna, "fill_color_path", NULL, 0, "Fill Color Path", "Path of property used to set the fill color of the control");
+ prop = RNA_def_string(ot->srna, "fill_color_path", NULL, 0, "Fill Color Path", "Path of property used to set the fill color of the control");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- RNA_def_string(ot->srna, "fill_color_override_path", NULL, 0, "Fill Color Override Path", "");
- RNA_def_string(ot->srna, "fill_color_override_test_path", NULL, 0, "Fill Color Override Test", "");
+ prop = RNA_def_string(ot->srna, "fill_color_override_path", NULL, 0, "Fill Color Override Path", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_string(ot->srna, "fill_color_override_test_path", NULL, 0, "Fill Color Override Test", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- RNA_def_string(ot->srna, "zoom_path", NULL, 0, "Zoom Path", "Path of property used to set the zoom level for the control");
+ prop = RNA_def_string(ot->srna, "zoom_path", NULL, 0, "Zoom Path", "Path of property used to set the zoom level for the control");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- RNA_def_string(ot->srna, "image_id", NULL, 0, "Image ID", "Path of ID that is used to generate an image for the control");
+ prop = RNA_def_string(ot->srna, "image_id", NULL, 0, "Image ID", "Path of ID that is used to generate an image for the control");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- RNA_def_boolean(ot->srna, "secondary_tex", false, "Secondary Texture", "Tweak brush secondary/mask texture");
+ prop = RNA_def_boolean(ot->srna, "secondary_tex", false, "Secondary Texture", "Tweak brush secondary/mask texture");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ************************** timer for testing ***************** */
@@ -3280,7 +3307,7 @@ static const EnumPropertyItem redraw_timer_type_items[] = {
static void redraw_timer_step(
- bContext *C, Main *bmain, Scene *scene, ViewLayer *view_layer,
+ bContext *C, Main *bmain, Scene *scene,
struct Depsgraph *depsgraph,
wmWindow *win, ScrArea *sa, ARegion *ar,
const int type, const int cfra)
@@ -3310,7 +3337,7 @@ static void redraw_timer_step(
CTX_wm_area_set(C, sa_iter);
for (ar_iter = sa_iter->regionbase.first; ar_iter; ar_iter = ar_iter->next) {
- if (ar_iter->swinid) {
+ if (ar_iter->visible) {
CTX_wm_region_set(C, ar_iter);
ED_region_do_draw(C, ar_iter);
ar_iter->do_draw = false;
@@ -3328,7 +3355,7 @@ static void redraw_timer_step(
}
else if (type == eRTAnimationStep) {
scene->r.cfra += (cfra == scene->r.cfra) ? 1 : -1;
- BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
}
else if (type == eRTAnimationPlay) {
/* play anim, return on same frame as started with */
@@ -3340,7 +3367,7 @@ static void redraw_timer_step(
if (scene->r.cfra > scene->r.efra)
scene->r.cfra = scene->r.sfra;
- BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
redraw_timer_window_swap(C);
}
}
@@ -3354,7 +3381,6 @@ static int redraw_timer_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
@@ -3372,7 +3398,7 @@ static int redraw_timer_exec(bContext *C, wmOperator *op)
time_start = PIL_check_seconds_timer();
for (a = 0; a < iter; a++) {
- redraw_timer_step(C, bmain, scene, view_layer, depsgraph, win, sa, ar, type, cfra);
+ redraw_timer_step(C, bmain, scene, depsgraph, win, sa, ar, type, cfra);
iter_steps += 1;
if (time_limit != 0.0) {
@@ -4054,6 +4080,7 @@ static const EnumPropertyItem *rna_id_itemf(
for (; id; id = id->next) {
if ((filter_ids != NULL) && filter_ids(user_data, id) == false) {
+ i++;
continue;
}
if (local == false || !ID_IS_LINKED(id)) {
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index fcb471530e0..d6a1eb81981 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -317,7 +317,7 @@ static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf
/* checkerboard for case alpha */
if (ibuf->planes == 32) {
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
imm_draw_box_checker_2d(offs_x, offs_y, offs_x + span_x, offs_y + span_y);
}
diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c
index 84b739a692e..b52fc4ae213 100644
--- a/source/blender/windowmanager/intern/wm_stereo.c
+++ b/source/blender/windowmanager/intern/wm_stereo.c
@@ -110,10 +110,10 @@ static void wm_method_draw_stereo3d_interlace(wmWindow *win)
const int sizey = WM_window_pixels_y(win);
/* wmOrtho for the screen has this same offset */
- float ratiox = sizex;
- float ratioy = sizey;
- float halfx = GLA_PIXEL_OFS;
- float halfy = GLA_PIXEL_OFS;
+ float ratiox = 1.0f;
+ float ratioy = 1.0f;
+ float halfx = GLA_PIXEL_OFS / sizex;
+ float halfy = GLA_PIXEL_OFS / sizex;
Gwn_VertFormat *format = immVertexFormat();
unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -124,7 +124,7 @@ static void wm_method_draw_stereo3d_interlace(wmWindow *win)
/* leave GL_TEXTURE0 as the latest bind texture */
for (int eye = 1; eye >= 0; eye--) {
glActiveTexture(GL_TEXTURE0 + eye);
- glBindTexture(drawdata[eye]->triple->target, drawdata[eye]->triple->bind);
+ glBindTexture(GL_TEXTURE_2D, drawdata[eye]->triple->bind);
}
immUniform1i("image_a", 0);
@@ -149,8 +149,9 @@ static void wm_method_draw_stereo3d_interlace(wmWindow *win)
immEnd();
immUnbindProgram();
- for (int eye = 0; eye < 2; eye++) {
- glBindTexture(drawdata[eye]->triple->target, 0);
+ for (int eye = 1; eye >= 0; eye--) {
+ glActiveTexture(GL_TEXTURE0 + eye);
+ glBindTexture(GL_TEXTURE_2D, 0);
}
}
@@ -194,7 +195,6 @@ static void wm_method_draw_stereo3d_sidebyside(wmWindow *win)
{
wmDrawData *drawdata;
wmDrawTriple *triple;
- float halfx, halfy, ratiox, ratioy;
int view;
int soffx;
bool cross_eyed = (win->stereo3d_format->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0;
@@ -203,6 +203,9 @@ static void wm_method_draw_stereo3d_sidebyside(wmWindow *win)
unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_ALPHA);
+ glActiveTexture(GL_TEXTURE0);
+
for (view = 0; view < 2; view ++) {
drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
triple = drawdata->triple;
@@ -217,27 +220,16 @@ static void wm_method_draw_stereo3d_sidebyside(wmWindow *win)
soffx = 0;
}
- const int sizex = triple->x;
- const int sizey = triple->y;
+ const int sizex = WM_window_pixels_x(win);
+ const int sizey = WM_window_pixels_y(win);
/* wmOrtho for the screen has this same offset */
- ratiox = sizex;
- ratioy = sizey;
- halfx = GLA_PIXEL_OFS;
- halfy = GLA_PIXEL_OFS;
-
- /* texture rectangle has unnormalized coordinates */
- if (triple->target == GL_TEXTURE_2D) {
- ratiox /= triple->x;
- ratioy /= triple->y;
- halfx /= triple->x;
- halfy /= triple->y;
- }
-
- /* TODO: if target is always same for both eyes, bind program & set uniform before loop */
- immBindBuiltinProgram((triple->target == GL_TEXTURE_2D) ? GPU_SHADER_3D_IMAGE_MODULATE_ALPHA : GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA);
+ const float ratiox = 1.0f;
+ const float ratioy = 1.0f;
+ const float halfx = GLA_PIXEL_OFS / sizex;
+ const float halfy = GLA_PIXEL_OFS / sizey;
- glBindTexture(triple->target, triple->bind);
+ glBindTexture(GL_TEXTURE_2D, triple->bind);
immUniform1f("alpha", 1.0f);
immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
@@ -257,18 +249,16 @@ static void wm_method_draw_stereo3d_sidebyside(wmWindow *win)
immVertex2f(pos, soffx, sizey);
immEnd();
-
- /* TODO: if target is always same for both eyes, unbind program & texture target after loop */
- glBindTexture(triple->target, 0);
- immUnbindProgram();
}
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ immUnbindProgram();
}
static void wm_method_draw_stereo3d_topbottom(wmWindow *win)
{
wmDrawData *drawdata;
wmDrawTriple *triple;
- float halfx, halfy, ratiox, ratioy;
int view;
int soffy;
@@ -276,6 +266,9 @@ static void wm_method_draw_stereo3d_topbottom(wmWindow *win)
unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_ALPHA);
+ glActiveTexture(GL_TEXTURE0);
+
for (view = 0; view < 2; view ++) {
drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
triple = drawdata->triple;
@@ -287,27 +280,16 @@ static void wm_method_draw_stereo3d_topbottom(wmWindow *win)
soffy = 0;
}
- const int sizex = triple->x;
- const int sizey = triple->y;
+ const int sizex = WM_window_pixels_x(win);
+ const int sizey = WM_window_pixels_y(win);
/* wmOrtho for the screen has this same offset */
- ratiox = sizex;
- ratioy = sizey;
- halfx = GLA_PIXEL_OFS;
- halfy = GLA_PIXEL_OFS;
-
- /* texture rectangle has unnormalized coordinates */
- if (triple->target == GL_TEXTURE_2D) {
- ratiox /= triple->x;
- ratioy /= triple->y;
- halfx /= triple->x;
- halfy /= triple->y;
- }
-
- /* TODO: if target is always same for both eyes, bind program & set uniforms before loop */
- immBindBuiltinProgram((triple->target == GL_TEXTURE_2D) ? GPU_SHADER_3D_IMAGE_MODULATE_ALPHA : GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA);
+ const float ratiox = 1.0f;
+ const float ratioy = 1.0f;
+ const float halfx = GLA_PIXEL_OFS / sizex;
+ const float halfy = GLA_PIXEL_OFS / sizey;
- glBindTexture(triple->target, triple->bind);
+ glBindTexture(GL_TEXTURE_2D, triple->bind);
immUniform1f("alpha", 1.0f);
immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
@@ -327,11 +309,10 @@ static void wm_method_draw_stereo3d_topbottom(wmWindow *win)
immVertex2f(pos, 0.0f, soffy + (sizey * 0.5f));
immEnd();
-
- /* TODO: if target is always same for both eyes, unbind program & texture target after loop */
- immUnbindProgram();
- glBindTexture(triple->target, 0);
}
+
+ immUnbindProgram();
+ glBindTexture(GL_TEXTURE_2D, 0);
}
void wm_method_draw_stereo3d(const bContext *UNUSED(C), wmWindow *win)
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index 1a8f71891c0..f34b5bf9c95 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -21,317 +21,85 @@
* Contributor(s): 2007 Blender Foundation (refactor)
*
* ***** END GPL LICENSE BLOCK *****
- *
- *
- * Subwindow opengl handling.
- * BTW: subwindows open/close in X11 are way too slow, tried it, and choose for my own system... (ton)
- *
*/
/** \file blender/windowmanager/intern/wm_subwindow.c
* \ingroup wm
*
- * Internal subwindows used for OpenGL state, used for regions and screens.
+ * OpenGL utilities for setting up 2D viewport for window and regions.
*/
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
+#include "BLI_math.h"
+#include "BLI_rect.h"
-#include "DNA_windowmanager_types.h"
#include "DNA_screen_types.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_utildefines.h"
+#include "DNA_windowmanager_types.h"
#include "BIF_gl.h"
#include "GPU_matrix.h"
#include "WM_api.h"
-#include "wm_subwindow.h"
-
-/**
- * \note #wmSubWindow stored in #wmWindow but not exposed outside this C file,
- * it seems a bit redundant (area regions can store it too, but we keep it
- * because we can store all kind of future opengl fanciness here.
- *
- * We use indices and array because:
- * - index has safety, no pointers from this C file hanging around
- * - fast lookups of indices with array, list would give overhead
- * - old code used it this way...
- * - keep option open to have 2 screens using same window
- */
-
-typedef struct wmSubWindow {
- struct wmSubWindow *next, *prev;
-
- rcti winrct;
- int swinid;
-} wmSubWindow;
-
-
-/* ******************* open, free, set, get data ******************** */
-
-/* not subwindow itself */
-static void wm_subwindow_free(wmSubWindow *UNUSED(swin))
-{
- /* future fancy stuff */
-}
-
-void wm_subwindows_free(wmWindow *win)
-{
- wmSubWindow *swin;
-
- for (swin = win->subwindows.first; swin; swin = swin->next)
- wm_subwindow_free(swin);
-
- BLI_freelistN(&win->subwindows);
-}
-
-
-int wm_subwindow_get_id(wmWindow *win)
-{
- if (win->curswin)
- return win->curswin->swinid;
- return 0;
-}
-
-static wmSubWindow *swin_from_swinid(wmWindow *win, int swinid)
-{
- wmSubWindow *swin;
-
- for (swin = win->subwindows.first; swin; swin = swin->next)
- if (swin->swinid == swinid)
- break;
- return swin;
-}
-
-static void wm_swin_size_get(wmSubWindow *swin, int *x, int *y)
-{
- *x = BLI_rcti_size_x(&swin->winrct) + 1;
- *y = BLI_rcti_size_y(&swin->winrct) + 1;
-}
-void wm_subwindow_size_get(wmWindow *win, int swinid, int *x, int *y)
+void wmViewport(const rcti *winrct)
{
- wmSubWindow *swin = swin_from_swinid(win, swinid);
-
- if (swin) {
- wm_swin_size_get(swin, x, y);
- }
-}
+ int width = BLI_rcti_size_x(winrct) + 1;
+ int height = BLI_rcti_size_y(winrct) + 1;
+ glViewport(winrct->xmin, winrct->ymin, width, height);
+ glScissor(winrct->xmin, winrct->ymin, width, height);
-static void wm_swin_origin_get(wmSubWindow *swin, int *x, int *y)
-{
- *x = swin->winrct.xmin;
- *y = swin->winrct.ymin;
-}
-void wm_subwindow_origin_get(wmWindow *win, int swinid, int *x, int *y)
-{
- wmSubWindow *swin = swin_from_swinid(win, swinid);
-
- if (swin) {
- wm_swin_origin_get(swin, x, y);
- }
+ wmOrtho2_pixelspace(width, height);
+ gpuLoadIdentity();
}
-
-static void wm_swin_matrix_get(wmWindow *win, wmSubWindow *swin, float mat[4][4])
+void wmPartialViewport(rcti *drawrct, const rcti *winrct, const rcti *partialrct)
{
- const bScreen *screen = WM_window_get_active_screen(win);
+ /* Setup part of the viewport for partial redraw. */
+ bool scissor_pad;
- /* used by UI, should find a better way to get the matrix there */
- if (swin->swinid == screen->mainwin) {
- int width, height;
-
- wm_swin_size_get(swin, &width, &height);
- orthographic_m4(mat, -GLA_PIXEL_OFS, (float)width - GLA_PIXEL_OFS, -GLA_PIXEL_OFS, (float)height - GLA_PIXEL_OFS, -100, 100);
+ if (partialrct->xmin == partialrct->xmax) {
+ /* Full region. */
+ *drawrct = *winrct;
+ scissor_pad = true;
}
else {
- gpuGetProjectionMatrix(mat);
- }
-}
-void wm_subwindow_matrix_get(wmWindow *win, int swinid, float mat[4][4])
-{
- wmSubWindow *swin = swin_from_swinid(win, swinid);
-
- if (swin) {
- wm_swin_matrix_get(win, swin, mat);
- }
-}
-
-
-static void wm_swin_rect_get(wmSubWindow *swin, rcti *r_rect)
-{
- *r_rect = swin->winrct;
-}
-void wm_subwindow_rect_get(wmWindow *win, int swinid, rcti *r_rect)
-{
- wmSubWindow *swin = swin_from_swinid(win, swinid);
-
- if (swin) {
- wm_swin_rect_get(swin, r_rect);
- }
-}
-
-
-static void wm_swin_rect_set(wmSubWindow *swin, const rcti *rect)
-{
- swin->winrct = *rect;
-}
-void wm_subwindow_rect_set(wmWindow *win, int swinid, const rcti *rect)
-{
- wmSubWindow *swin = swin_from_swinid(win, swinid);
-
- if (swin) {
- wm_swin_rect_set(swin, rect);
- }
-}
-
-
-/* always sets pixel-precise 2D window/view matrices */
-/* coords is in whole pixels. xmin = 15, xmax = 16: means window is 2 pix big */
-int wm_subwindow_open(wmWindow *win, const rcti *winrct, bool activate)
-{
- wmSubWindow *swin;
- int width, height;
- int freewinid = 1;
-
- for (swin = win->subwindows.first; swin; swin = swin->next)
- if (freewinid <= swin->swinid)
- freewinid = swin->swinid + 1;
-
- win->curswin = swin = MEM_callocN(sizeof(wmSubWindow), "swinopen");
- BLI_addtail(&win->subwindows, swin);
-
- swin->swinid = freewinid;
- swin->winrct = *winrct;
-
- if (activate) {
- /* and we appy it all right away */
- wmSubWindowSet(win, swin->swinid);
-
- /* extra service */
- wm_swin_size_get(swin, &width, &height);
- wmOrtho2_pixelspace(width, height);
- gpuLoadIdentity();
+ /* Partial redraw, clipped to region. */
+ BLI_rcti_isect(winrct, partialrct, drawrct);
+ scissor_pad = false;
}
- return swin->swinid;
-}
+ int width = BLI_rcti_size_x(winrct) + 1;
+ int height = BLI_rcti_size_y(winrct) + 1;
-void wm_subwindow_close(wmWindow *win, int swinid)
-{
- wmSubWindow *swin = swin_from_swinid(win, swinid);
+ int scissor_width = BLI_rcti_size_x(drawrct);
+ int scissor_height = BLI_rcti_size_y(drawrct);
- if (swin) {
- if (swin == win->curswin)
- win->curswin = NULL;
- wm_subwindow_free(swin);
- BLI_remlink(&win->subwindows, swin);
- MEM_freeN(swin);
+ /* Partial redraw rect uses different convention than region rect,
+ * so compensate for that here. One pixel offset is noticeable with
+ * viewport border render. */
+ if (scissor_pad) {
+ scissor_width += 1;
+ scissor_height += 1;
}
- else {
- printf("%s: Internal error, bad winid: %d\n", __func__, swinid);
- }
-}
-/* pixels go from 0-99 for a 100 pixel window */
-void wm_subwindow_position(wmWindow *win, int swinid, const rcti *winrct, bool activate)
-{
- wmSubWindow *swin = swin_from_swinid(win, swinid);
-
- if (swin) {
- const int winsize_x = WM_window_pixels_x(win);
- const int winsize_y = WM_window_pixels_y(win);
+ glViewport(winrct->xmin, winrct->ymin, width, height);
+ glScissor(drawrct->xmin, drawrct->ymin, scissor_width, scissor_height);
- int width, height;
-
- swin->winrct = *winrct;
-
- /* CRITICAL, this clamping ensures that
- * the viewport never goes outside the screen
- * edges (assuming the x, y coords aren't
- * outside). This caused a hardware lock
- * on Matrox cards if it happens.
- *
- * Really Blender should never _ever_ try
- * to do such a thing, but just to be safe
- * clamp it anyway (or fix the bScreen
- * scaling routine, and be damn sure you
- * fixed it). - zr (2001!)
- */
-
- if (swin->winrct.xmax > winsize_x)
- swin->winrct.xmax = winsize_x;
- if (swin->winrct.ymax > winsize_y)
- swin->winrct.ymax = winsize_y;
-
- if (activate) {
- /* extra service */
- wmSubWindowSet(win, swinid);
- wm_swin_size_get(swin, &width, &height);
- wmOrtho2_pixelspace(width, height);
- }
- }
- else {
- printf("%s: Internal error, bad winid: %d\n", __func__, swinid);
- }
+ wmOrtho2_pixelspace(width, height);
+ gpuLoadIdentity();
}
-/* ---------------- WM versions of OpenGL style API calls ------------------------ */
-/* ----------------- exported in WM_api.h ------------------------------------------------------ */
-
-/* internal state, no threaded opengl! XXX */
-static wmWindow *_curwindow = NULL;
-static wmSubWindow *_curswin = NULL;
-
-void wmSubWindowScissorSet(wmWindow *win, int swinid, const rcti *srct, bool srct_pad)
+void wmWindowViewport(wmWindow *win)
{
- int width, height;
- _curswin = swin_from_swinid(win, swinid);
-
- if (_curswin == NULL) {
- printf("%s %d: doesn't exist\n", __func__, swinid);
- return;
- }
-
- win->curswin = _curswin;
- _curwindow = win;
-
- width = BLI_rcti_size_x(&_curswin->winrct) + 1;
- height = BLI_rcti_size_y(&_curswin->winrct) + 1;
- glViewport(_curswin->winrct.xmin, _curswin->winrct.ymin, width, height);
-
- if (srct) {
- int scissor_width = BLI_rcti_size_x(srct);
- int scissor_height = BLI_rcti_size_y(srct);
+ int width = WM_window_pixels_x(win);
+ int height = WM_window_pixels_y(win);
- /* typically a single pixel doesn't matter,
- * but one pixel offset is noticeable with viewport border render */
- if (srct_pad) {
- scissor_width += 1;
- scissor_height += 1;
- }
+ glViewport(0, 0, width, height);
+ glScissor(0, 0, width, height);
- glScissor(srct->xmin, srct->ymin, scissor_width, scissor_height);
- }
- else
- glScissor(_curswin->winrct.xmin, _curswin->winrct.ymin, width, height);
-
wmOrtho2_pixelspace(width, height);
gpuLoadIdentity();
-
- glFlush();
-}
-
-/* enable the WM versions of opengl calls */
-void wmSubWindowSet(wmWindow *win, int swinid)
-{
- wmSubWindowScissorSet(win, swinid, NULL, true);
}
void wmOrtho2(float x1, float x2, float y1, float y2)
@@ -348,9 +116,7 @@ static void wmOrtho2_offset(const float x, const float y, const float ofs)
wmOrtho2(ofs, x + ofs, ofs, y + ofs);
}
-/**
- * default pixel alignment.
- */
+/* Default pixel alignment for regions. */
void wmOrtho2_region_pixelspace(const ARegion *ar)
{
wmOrtho2_offset(ar->winx, ar->winy, -0.01f);
@@ -361,5 +127,9 @@ void wmOrtho2_pixelspace(const float x, const float y)
wmOrtho2_offset(x, y, -GLA_PIXEL_OFS);
}
-/* ********** END MY WINDOW ************** */
-
+void wmGetProjectionMatrix(float mat[4][4], const rcti *winrct)
+{
+ int width = BLI_rcti_size_x(winrct) + 1;
+ int height = BLI_rcti_size_y(winrct) + 1;
+ orthographic_m4(mat, -GLA_PIXEL_OFS, (float)width - GLA_PIXEL_OFS, -GLA_PIXEL_OFS, (float)height - GLA_PIXEL_OFS, -100, 100);
+}
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 0e07b66996d..9b0d8db68ce 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -68,7 +68,6 @@
#include "wm.h"
#include "wm_draw.h"
#include "wm_window.h"
-#include "wm_subwindow.h"
#include "wm_event_system.h"
#include "ED_scene.h"
@@ -80,14 +79,18 @@
#include "PIL_time.h"
+#include "GPU_batch.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
+#include "GPU_framebuffer.h"
#include "GPU_init_exit.h"
#include "GPU_immediate.h"
#include "BLF_api.h"
#include "UI_resources.h"
+#include "../../../intern/gawain/gawain/gwn_context.h"
+
/* for assert */
#ifndef NDEBUG
# include "BLI_threads.h"
@@ -170,12 +173,23 @@ static void wm_window_check_position(rcti *rect)
}
-static void wm_ghostwindow_destroy(wmWindow *win)
+static void wm_ghostwindow_destroy(wmWindowManager *wm, wmWindow *win)
{
if (win->ghostwin) {
+ /* We need this window's opengl context active to discard it. */
+ GHOST_ActivateWindowDrawingContext(win->ghostwin);
+ GWN_context_active_set(win->gwnctx);
+
+ /* Delete local gawain objects. */
+ GWN_context_discard(win->gwnctx);
+
GHOST_DisposeWindow(g_system, win->ghostwin);
win->ghostwin = NULL;
- win->multisamples = 0;
+ win->gwnctx = NULL;
+
+ /* prevents non-drawable state of main windows (bugs #22967 and #25071, possibly #22477 too) */
+ wm->windrawable = NULL;
+ wm->winactive = NULL;
}
}
@@ -194,11 +208,6 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win)
CTX_wm_window_set(C, NULL);
}
- /* always set drawable and active to NULL,
- * prevents non-drawable state of main windows (bugs #22967 and #25071, possibly #22477 too) */
- wm->windrawable = NULL;
- wm->winactive = NULL;
-
/* end running jobs, a job end also removes its timer */
for (wt = wm->timers.first; wt; wt = wtnext) {
wtnext = wt->next;
@@ -216,11 +225,10 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win)
if (win->eventstate) MEM_freeN(win->eventstate);
wm_event_free_all(win);
- wm_subwindows_free(win);
wm_draw_data_free(win);
- wm_ghostwindow_destroy(win);
+ wm_ghostwindow_destroy(wm, win);
BKE_workspace_instance_hook_free(G.main, win->workspace_hook);
MEM_freeN(win->stereo3d_format);
@@ -327,11 +335,158 @@ wmWindow *wm_window_copy_test(bContext *C, wmWindow *win_src, const bool duplica
}
}
+
+/* -------------------------------------------------------------------- */
+/** \name Quit Confirmation Dialog
+ * \{ */
+
+/** Cancel quitting and close the dialog */
+static void wm_block_confirm_quit_cancel(bContext *C, void *arg_block, void *UNUSED(arg))
+{
+ wmWindow *win = CTX_wm_window(C);
+ UI_popup_block_close(C, win, arg_block);
+}
+
+/** Discard the file changes and quit */
+static void wm_block_confirm_quit_discard(bContext *C, void *arg_block, void *UNUSED(arg))
+{
+ wmWindow *win = CTX_wm_window(C);
+ UI_popup_block_close(C, win, arg_block);
+ WM_exit(C);
+}
+
+/* Save changes and quit */
+static void wm_block_confirm_quit_save(bContext *C, void *arg_block, void *UNUSED(arg))
+{
+ PointerRNA props_ptr;
+ wmWindow *win = CTX_wm_window(C);
+
+ UI_popup_block_close(C, win, arg_block);
+
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_save_mainfile", false);
+
+ WM_operator_properties_create_ptr(&props_ptr, ot);
+ RNA_boolean_set(&props_ptr, "exit", true);
+ /* No need for second confirmation popup. */
+ RNA_boolean_set(&props_ptr, "check_existing", false);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ WM_operator_properties_free(&props_ptr);
+}
+
+
+/* Build the confirm dialog UI */
+static uiBlock *block_create_confirm_quit(struct bContext *C, struct ARegion *ar, void *UNUSED(arg1))
+{
+
+ uiStyle *style = UI_style_get();
+ uiBlock *block = UI_block_begin(C, ar, "confirm_quit_popup", UI_EMBOSS);
+
+ UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT);
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ uiLayout *layout = UI_block_layout(
+ block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 10, 2, U.widget_unit * 24, U.widget_unit * 6, 0, style);
+
+ /* Text and some vertical space */
+ {
+ char *message;
+ if (G.main->name[0] == '\0') {
+ message = BLI_strdup(IFACE_("This file has not been saved yet. Save before closing?"));
+ }
+ else {
+ const char *basename = BLI_path_basename(G.main->name);
+ message = BLI_sprintfN(IFACE_("Save changes to \"%s\" before closing?"), basename);
+ }
+ uiItemL(layout, message, ICON_ERROR);
+ MEM_freeN(message);
+ }
+
+ uiItemS(layout);
+ uiItemS(layout);
+
+
+ /* Buttons */
+ uiBut *but;
+
+ uiLayout *split = uiLayoutSplit(layout, 0.0f, true);
+
+ uiLayout *col = uiLayoutColumn(split, false);
+
+ but = uiDefIconTextBut(
+ block, UI_BTYPE_BUT, 0, ICON_SCREEN_BACK, IFACE_("Cancel"), 0, 0, 0, UI_UNIT_Y,
+ NULL, 0, 0, 0, 0, TIP_("Do not quit"));
+ UI_but_func_set(but, wm_block_confirm_quit_cancel, block, NULL);
+
+ /* empty space between buttons */
+ col = uiLayoutColumn(split, false);
+ uiItemS(col);
+
+ col = uiLayoutColumn(split, 1);
+ but = uiDefIconTextBut(
+ block, UI_BTYPE_BUT, 0, ICON_CANCEL, IFACE_("Discard Changes"), 0, 0, 50, UI_UNIT_Y,
+ NULL, 0, 0, 0, 0, TIP_("Discard changes and quit"));
+ UI_but_func_set(but, wm_block_confirm_quit_discard, block, NULL);
+
+ col = uiLayoutColumn(split, 1);
+ but = uiDefIconTextBut(
+ block, UI_BTYPE_BUT, 0, ICON_FILE_TICK, IFACE_("Save & Quit"), 0, 0, 50, UI_UNIT_Y,
+ NULL, 0, 0, 0, 0, TIP_("Save and quit"));
+ UI_but_func_set(but, wm_block_confirm_quit_save, block, NULL);
+
+ UI_block_bounds_set_centered(block, 10);
+
+ return block;
+}
+
+
+/**
+ * Call the confirm dialog on quitting. It's displayed in the context window so
+ * caller should set it as desired.
+ */
+static void wm_confirm_quit(bContext *C)
+{
+ wmWindow *win = CTX_wm_window(C);
+
+ if (GHOST_SupportsNativeDialogs() == 0) {
+ UI_popup_block_invoke(C, block_create_confirm_quit, NULL);
+ }
+ else if (GHOST_confirmQuit(win->ghostwin)) {
+ wm_exit_schedule_delayed(C);
+ }
+}
+
+/**
+ * Call the quit confirmation prompt or exit directly if needed. The use can
+ * still cancel via the confirmation popup. Also, this may not quit Blender
+ * immediately, but rather schedule the closing.
+ *
+ * \param win The window to show the confirmation popup/window in.
+ */
+void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win_ctx = CTX_wm_window(C);
+
+ /* The popup will be displayed in the context window which may not be set
+ * here (this function gets called outside of normal event handling loop). */
+ CTX_wm_window_set(C, win);
+
+ if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved && !G.background) {
+ wm_confirm_quit(C);
+ }
+ else {
+ wm_exit_schedule_delayed(C);
+ }
+
+ CTX_wm_window_set(C, win_ctx);
+}
+
+/** \} */
+
/* this is event from ghost, or exit-blender op */
void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
{
wmWindow *tmpwin;
- bool do_exit = false;
/* first check if we have to quit (there are non-temp remaining windows) */
for (tmpwin = wm->windows.first; tmpwin; tmpwin = tmpwin->next) {
@@ -341,19 +496,8 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
break;
}
- if (tmpwin == NULL)
- do_exit = 1;
-
- if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved && !G.background) {
- if (do_exit) {
- if (!GHOST_confirmQuit(win->ghostwin))
- return;
- }
- }
-
- /* let WM_exit do all freeing, for correct quit.blend save */
- if (do_exit) {
- WM_exit(C);
+ if (tmpwin == NULL) {
+ wm_quit_with_optional_confirmation_prompt(C, win);
}
else {
bScreen *screen = WM_window_get_active_screen(win);
@@ -373,9 +517,22 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
if (screen) {
ED_screen_exit(C, win, screen);
}
-
+
+ if (tmpwin) {
+ BLF_batch_reset();
+ gpu_batch_presets_reset();
+ immDeactivate();
+ }
+
wm_window_free(C, wm, win);
-
+
+ /* keep imediatemode active before the next `wm_window_make_drawable` call */
+ if (tmpwin) {
+ GHOST_ActivateWindowDrawingContext(tmpwin->ghostwin);
+ GWN_context_active_set(tmpwin->gwnctx);
+ immActivate();
+ }
+
/* if temp screen, delete it after window free (it stops jobs that can access it) */
if (screen && screen->temp) {
Main *bmain = CTX_data_main(C);
@@ -461,16 +618,8 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm
{
GHOST_WindowHandle ghostwin;
GHOST_GLSettings glSettings = {0};
- static int multisamples = -1;
int scr_w, scr_h, posy;
- /* force setting multisamples only once, it requires restart - and you cannot
- * mix it, either all windows have it, or none (tested in OSX opengl) */
- if (multisamples == -1)
- multisamples = U.ogl_multisamples;
-
- glSettings.numOfAASamples = multisamples;
-
/* a new window is created when pageflip mode is required for a window */
if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP)
glSettings.flags |= GHOST_glStereoVisual;
@@ -484,17 +633,19 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm
ghostwin = GHOST_CreateWindow(g_system, title,
win->posx, posy, win->sizex, win->sizey,
-#ifdef __APPLE__
- /* we agreed to not set any fullscreen or iconized state on startup */
- GHOST_kWindowStateNormal,
-#else
(GHOST_TWindowState)win->windowstate,
-#endif
GHOST_kDrawingContextTypeOpenGL,
glSettings);
-
+
if (ghostwin) {
GHOST_RectangleHandle bounds;
+
+ /* XXX Fix crash when a new window is created.
+ * However this should be move somewhere else. (fclem) */
+ BLF_batch_reset();
+ gpu_batch_presets_reset();
+
+ win->gwnctx = GWN_context_create();
/* the new window has already been made drawable upon creation */
wm->windrawable = win;
@@ -508,9 +659,6 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm
if (win->eventstate == NULL)
win->eventstate = MEM_callocN(sizeof(wmEvent), "window event state");
- /* store multisamples window was created with, in case user prefs change */
- win->multisamples = multisamples;
-
/* store actual window size in blender window */
bounds = GHOST_GetClientBounds(win->ghostwin);
@@ -546,7 +694,7 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm
}
/**
- * Initialize #wmWindows without ghostwin, open these and clear.
+ * Initialize #wmWindow without ghostwin, open these and clear.
*
* window size is read from window, if 0 it uses prefsize
* called in #WM_check, also inits stuff after file read.
@@ -756,7 +904,11 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i
WM_window_set_active_layout(win, workspace, layout);
}
- if (WM_window_get_active_scene(win) != scene) {
+ if (win->scene == NULL) {
+ win->scene = scene;
+ }
+ /* In case we reuse an already existing temp window (see win lookup above). */
+ else if (WM_window_get_active_scene(win) != scene) {
WM_window_change_active_scene(bmain, C, win, scene);
}
@@ -868,7 +1020,7 @@ int wm_window_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(even
WorkSpace *workspace = WM_window_get_active_workspace(win);
ListBase *listbase = BKE_workspace_layouts_get(workspace);
- if (BLI_listbase_count_ex(listbase, 2) == 1) {
+ if (BLI_listbase_count_at_most(listbase, 2) == 1) {
RNA_enum_set(op->ptr, "screen", 0);
return wm_window_new_exec(C, op);
}
@@ -1012,16 +1164,21 @@ static int query_qual(modifierKeyType qual)
void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
{
+ BLI_assert(GPU_framebuffer_current_get() == 0);
+
if (win != wm->windrawable && win->ghostwin) {
// win->lmbut = 0; /* keeps hanging when mousepressed while other window opened */
-
+
wm->windrawable = win;
if (G.debug & G_DEBUG_EVENTS) {
printf("%s: set drawable %d\n", __func__, win->winid);
}
+ BLF_batch_reset();
+ gpu_batch_presets_reset();
immDeactivate();
GHOST_ActivateWindowDrawingContext(win->ghostwin);
+ GWN_context_active_set(win->gwnctx);
immActivate();
/* this can change per window */
@@ -1029,6 +1186,28 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
}
}
+/* Reset active the current window opengl drawing context. */
+void wm_window_reset_drawable(void)
+{
+ BLI_assert(BLI_thread_is_main());
+ BLI_assert(GPU_framebuffer_current_get() == 0);
+ wmWindowManager *wm = G.main->wm.first;
+
+ if (wm == NULL)
+ return;
+
+ wmWindow *win = wm->windrawable;
+
+ if (win && win->ghostwin) {
+ BLF_batch_reset();
+ gpu_batch_presets_reset();
+ immDeactivate();
+ GHOST_ActivateWindowDrawingContext(win->ghostwin);
+ GWN_context_active_set(win->gwnctx);
+ immActivate();
+ }
+}
+
/* called by ghost, here we handle events for windows themselves or send to event system */
/* mouse coordinate converversion happens here */
static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr)
@@ -1612,6 +1791,7 @@ wmTimer *WM_event_add_timer_notifier(wmWindowManager *wm, wmWindow *win, unsigne
wt->timestep = timestep;
wt->win = win;
wt->customdata = SET_UINT_IN_POINTER(type);
+ wt->flags |= WM_TIMER_NO_FREE_CUSTOM_DATA;
BLI_addtail(&wm->timers, wt);
@@ -1633,8 +1813,9 @@ void WM_event_remove_timer(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *
wm->reports.reporttimer = NULL;
BLI_remlink(&wm->timers, wt);
- if (wt->customdata)
+ if (wt->customdata != NULL && (wt->flags & WM_TIMER_NO_FREE_CUSTOM_DATA) == 0) {
MEM_freeN(wt->customdata);
+ }
MEM_freeN(wt);
/* there might be events in queue with this timer as customdata */
@@ -1796,7 +1977,6 @@ void wm_window_raise(wmWindow *win)
void wm_window_swap_buffers(wmWindow *win)
{
-
#ifdef WIN32
glDisable(GL_SCISSOR_TEST);
GHOST_SwapWindowBuffers(win->ghostwin);
@@ -1959,10 +2139,9 @@ Scene *WM_window_get_active_scene(const wmWindow *win)
void WM_window_change_active_scene(Main *bmain, bContext *C, wmWindow *win, Scene *scene_new)
{
const bScreen *screen = WM_window_get_active_screen(win);
+ Scene *scene_old = win->scene;
- ED_scene_exit(C);
- win->scene = scene_new;
- ED_scene_changed_update(bmain, C, scene_new, screen);
+ ED_scene_change_update(bmain, C, win, screen, scene_old, scene_new);
}
WorkSpace *WM_window_get_active_workspace(const wmWindow *win)
@@ -1998,6 +2177,26 @@ void WM_window_set_active_screen(wmWindow *win, WorkSpace *workspace, bScreen *s
BKE_workspace_active_screen_set(win->workspace_hook, workspace, screen);
}
+struct ViewLayer *WM_window_get_active_view_layer_ex(const wmWindow *win, Scene **r_scene)
+{
+ const WorkSpace *workspace = WM_window_get_active_workspace(win);
+ Scene *scene = WM_window_get_active_scene(win);
+ /* May be NULL in rare cases like closing Blender */
+ bScreen *screen = (LIKELY(workspace != NULL) ? BKE_workspace_active_screen_get(win->workspace_hook) : NULL);
+ if (screen != NULL) {
+ if (r_scene) {
+ *r_scene = scene;
+ }
+ return BKE_workspace_view_layer_get(workspace, scene);
+ }
+ return NULL;
+}
+
+struct ViewLayer *WM_window_get_active_view_layer(const wmWindow *win)
+{
+ return WM_window_get_active_view_layer_ex(win, NULL);
+}
+
bool WM_window_is_temp_screen(const wmWindow *win)
{
const bScreen *screen = WM_window_get_active_screen(win);
@@ -2022,3 +2221,34 @@ void wm_window_IME_end(wmWindow *win)
win->ime_data = NULL;
}
#endif /* WITH_INPUT_IME */
+
+/* ****** direct opengl context management ****** */
+
+void *WM_opengl_context_create(void)
+{
+ /* On Windows there is a problem creating contexts that share lists
+ * from one context that is current in another thread.
+ * So we should call this function only on the main thread.
+ */
+ BLI_assert(BLI_thread_is_main());
+ BLI_assert(GPU_framebuffer_current_get() == 0);
+ return GHOST_CreateOpenGLContext(g_system);
+}
+
+void WM_opengl_context_dispose(void *context)
+{
+ BLI_assert(GPU_framebuffer_current_get() == 0);
+ GHOST_DisposeOpenGLContext(g_system, (GHOST_ContextHandle)context);
+}
+
+void WM_opengl_context_activate(void *context)
+{
+ BLI_assert(GPU_framebuffer_current_get() == 0);
+ GHOST_ActivateOpenGLContext((GHOST_ContextHandle)context);
+}
+
+void WM_opengl_context_release(void *context)
+{
+ BLI_assert(GPU_framebuffer_current_get() == 0);
+ GHOST_ReleaseOpenGLContext((GHOST_ContextHandle)context);
+}
diff --git a/source/blender/windowmanager/manipulators/WM_manipulator_api.h b/source/blender/windowmanager/manipulators/WM_manipulator_api.h
index 53bee9c6775..97fcb4513be 100644
--- a/source/blender/windowmanager/manipulators/WM_manipulator_api.h
+++ b/source/blender/windowmanager/manipulators/WM_manipulator_api.h
@@ -331,4 +331,6 @@ void WM_manipulator_group_type_unlink_delayed(const char *idname);
/* Utilities */
bool WM_manipulator_context_check_drawstep(const struct bContext *C, eWM_ManipulatorMapDrawStep step);
+bool WM_manipulator_group_type_poll(const struct bContext *C, const struct wmManipulatorGroupType *wgt);
+
#endif /* __WM_MANIPULATOR_API_H__ */
diff --git a/source/blender/windowmanager/manipulators/WM_manipulator_types.h b/source/blender/windowmanager/manipulators/WM_manipulator_types.h
index 6d83f411db1..8a5580582d7 100644
--- a/source/blender/windowmanager/manipulators/WM_manipulator_types.h
+++ b/source/blender/windowmanager/manipulators/WM_manipulator_types.h
@@ -341,6 +341,7 @@ typedef struct wmManipulatorGroupTypeRef {
typedef struct wmManipulatorGroupType {
const char *idname; /* MAX_NAME */
const char *name; /* manipulator-group name - displayed in UI (keymap editor) */
+ char owner_id[64]; /* MAX_NAME */
/* poll if manipulator-map should be visible */
wmManipulatorGroupFnPoll poll;
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
index 0e63f3d6ffe..31861df1db2 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
@@ -44,6 +44,7 @@
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_report.h"
+#include "BKE_workspace.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -201,10 +202,17 @@ void wm_manipulatorgroup_ensure_initialized(wmManipulatorGroup *mgroup, const bC
}
}
-bool wm_manipulatorgroup_is_visible(const wmManipulatorGroup *mgroup, const bContext *C)
+bool WM_manipulator_group_type_poll(const bContext *C, const struct wmManipulatorGroupType *wgt)
{
+ /* If we're tagged, only use compatible. */
+ if (wgt->owner_id[0] != '\0') {
+ const WorkSpace *workspace = CTX_wm_workspace(C);
+ if (BKE_workspace_owner_id_check(workspace, wgt->owner_id) == false) {
+ return false;
+ }
+ }
/* Check for poll function, if manipulator-group belongs to an operator, also check if the operator is running. */
- return (!mgroup->type->poll || mgroup->type->poll(C, mgroup->type));
+ return (!wgt->poll || wgt->poll(C, (wmManipulatorGroupType *)wgt));
}
bool wm_manipulatorgroup_is_visible_in_drawstep(
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h b/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
index b7982cf00df..a131c6c5069 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
@@ -75,7 +75,6 @@ struct wmManipulator *wm_manipulatorgroup_find_intersected_manipulator(
void wm_manipulatorgroup_intersectable_manipulators_to_list(
const struct wmManipulatorGroup *mgroup, struct ListBase *listbase);
void wm_manipulatorgroup_ensure_initialized(struct wmManipulatorGroup *mgroup, const struct bContext *C);
-bool wm_manipulatorgroup_is_visible(const struct wmManipulatorGroup *mgroup, const struct bContext *C);
bool wm_manipulatorgroup_is_visible_in_drawstep(
const struct wmManipulatorGroup *mgroup, const eWM_ManipulatorMapDrawStep drawstep);
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c
index a9875020fbb..d774c4e4a2e 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c
@@ -272,7 +272,7 @@ static GHash *WM_manipulatormap_manipulator_hash_new(
/* collect manipulators */
for (wmManipulatorGroup *mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) {
- if (!mgroup->type->poll || mgroup->type->poll(C, mgroup->type)) {
+ if (WM_manipulator_group_type_poll(C, mgroup->type)) {
for (wmManipulator *mpr = mgroup->manipulators.first; mpr; mpr = mpr->next) {
if ((include_hidden || (mpr->flag & WM_MANIPULATOR_HIDDEN) == 0) &&
(!poll || poll(mpr, data)))
@@ -350,7 +350,7 @@ static void manipulatormap_prepare_drawing(
for (wmManipulatorGroup *mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) {
/* check group visibility - drawstep first to avoid unnecessary call of group poll callback */
if (!wm_manipulatorgroup_is_visible_in_drawstep(mgroup, drawstep) ||
- !wm_manipulatorgroup_is_visible(mgroup, C))
+ !WM_manipulator_group_type_poll(C, mgroup->type))
{
continue;
}
@@ -390,16 +390,9 @@ static void manipulators_draw_list(const wmManipulatorMap *mmap, const bContext
return;
}
- const bool draw_multisample = (U.ogl_multisamples != USER_MULTISAMPLE_NONE);
-
/* TODO this will need it own shader probably? don't think it can be handled from that point though. */
/* const bool use_lighting = (U.manipulator_flag & V3D_MANIPULATOR_SHADED) != 0; */
- /* enable multisampling */
- if (draw_multisample) {
- glEnable(GL_MULTISAMPLE);
- }
-
bool is_depth_prev = false;
/* draw_manipulators contains all visible manipulators - draw them */
@@ -435,10 +428,6 @@ static void manipulators_draw_list(const wmManipulatorMap *mmap, const bContext
if (is_depth_prev) {
glDisable(GL_DEPTH_TEST);
}
-
- if (draw_multisample) {
- glDisable(GL_MULTISAMPLE);
- }
}
void WM_manipulatormap_draw(
@@ -608,7 +597,7 @@ wmManipulator *wm_manipulatormap_highlight_find(
continue;
}
- if (wm_manipulatorgroup_is_visible(mgroup, C)) {
+ if (WM_manipulator_group_type_poll(C, mgroup->type)) {
eWM_ManipulatorMapDrawStep step;
if (mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) {
step = WM_MANIPULATORMAP_DRAWSTEP_3D;
@@ -619,7 +608,7 @@ wmManipulator *wm_manipulatormap_highlight_find(
if (do_step[step]) {
if ((mmap->update_flag[step] & MANIPULATORMAP_IS_REFRESH_CALLBACK) &&
- (mgroup->type->refresh != NULL))
+ (mgroup->type->refresh != NULL))
{
mgroup->type->refresh(C, mgroup);
/* cleared below */
@@ -760,7 +749,7 @@ static bool wm_manipulatormap_select_all_intern(
int i;
bool changed = false;
- wm_manipulatormap_select_array_ensure_len_alloc(mmap, BLI_ghash_size(hash));
+ wm_manipulatormap_select_array_ensure_len_alloc(mmap, BLI_ghash_len(hash));
GHASH_ITER_INDEX (gh_iter, hash, i) {
wmManipulator *mpr_iter = BLI_ghashIterator_getValue(&gh_iter);
@@ -769,7 +758,7 @@ static bool wm_manipulatormap_select_all_intern(
/* highlight first manipulator */
wm_manipulatormap_highlight_set(mmap, C, msel->items[0], msel->items[0]->highlight_part);
- BLI_assert(BLI_ghash_size(hash) == msel->len);
+ BLI_assert(BLI_ghash_len(hash) == msel->len);
BLI_ghash_free(hash, NULL, NULL);
return changed;
@@ -995,7 +984,7 @@ void WM_manipulatormap_message_subscribe(
bContext *C, wmManipulatorMap *mmap, ARegion *ar, struct wmMsgBus *mbus)
{
for (wmManipulatorGroup *mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) {
- if (!wm_manipulatorgroup_is_visible(mgroup, C)) {
+ if (!WM_manipulator_group_type_poll(C, mgroup->type)) {
continue;
}
for (wmManipulator *mpr = mgroup->manipulators.first; mpr; mpr = mpr->next) {
diff --git a/source/blender/windowmanager/message_bus/intern/wm_message_bus.c b/source/blender/windowmanager/message_bus/intern/wm_message_bus.c
index 7183655b0de..06a9c2de69b 100644
--- a/source/blender/windowmanager/message_bus/intern/wm_message_bus.c
+++ b/source/blender/windowmanager/message_bus/intern/wm_message_bus.c
@@ -40,7 +40,7 @@
/** \name Public API
* \{ */
-static wmMsgTypeInfo wm_msg_types[WM_MSG_TYPE_NUM] = {NULL};
+static wmMsgTypeInfo wm_msg_types[WM_MSG_TYPE_NUM] = {{{NULL}}};
typedef void (*wmMsgTypeInitFn)(wmMsgTypeInfo *);
@@ -86,6 +86,9 @@ void WM_msgbus_clear_by_owner(struct wmMsgBus *mbus, void *owner)
for (wmMsgSubscribeValueLink *msg_lnk = msg_key->values.first; msg_lnk; msg_lnk = msg_lnk_next) {
msg_lnk_next = msg_lnk->next;
if (msg_lnk->params.owner == owner) {
+ if (msg_lnk->params.tag) {
+ mbus->messages_tag_count -= 1;
+ }
if (msg_lnk->params.free_data) {
msg_lnk->params.free_data(msg_key, &msg_lnk->params);
}
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 f9d8d968b84..c9b43cc2a91 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
@@ -148,7 +148,6 @@ static void wm_msg_rna_update_by_id(
}
}
- printf("AAA ~ %d\n", remove);
if (remove) {
/* Failed to persist, remove the key. */
BLI_remlink(&mbus->messages, key);
@@ -301,14 +300,14 @@ void WM_msg_subscribe_ID(
struct wmMsgBus *mbus, ID *id, 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/intern/wm_message_bus_static.c b/source/blender/windowmanager/message_bus/intern/wm_message_bus_static.c
index 59bebad7f7b..d768e77c8fe 100644
--- a/source/blender/windowmanager/message_bus/intern/wm_message_bus_static.c
+++ b/source/blender/windowmanager/message_bus/intern/wm_message_bus_static.c
@@ -18,7 +18,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/windowmanager/intern/wm_message_bus_static.c
+/** \file blender/windowmanager/intern/message_bus/wm_message_bus_static.c
* \ingroup wm
*/
diff --git a/source/blender/windowmanager/message_bus/wm_message_bus.h b/source/blender/windowmanager/message_bus/wm_message_bus.h
index 53f283cacd2..8a800d18101 100644
--- a/source/blender/windowmanager/message_bus/wm_message_bus.h
+++ b/source/blender/windowmanager/message_bus/wm_message_bus.h
@@ -18,7 +18,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/windowmanager/wm_message_bus.h
+/** \file blender/windowmanager/message_bus/wm_message_bus.h
* \ingroup wm
*/
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index 7fe6db4e470..b2e8c914fa8 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -45,6 +45,9 @@ typedef struct wmPaintCursor {
void (*draw)(bContext *C, int, int, void *customdata);
} wmPaintCursor;
+
+void wm_exit_schedule_delayed(const bContext *C);
+
extern void wm_close_and_free(bContext *C, wmWindowManager *);
extern void wm_close_and_free_all(bContext *C, ListBase *);
diff --git a/source/blender/windowmanager/wm_draw.h b/source/blender/windowmanager/wm_draw.h
index 56dff304719..fa3d443e6ae 100644
--- a/source/blender/windowmanager/wm_draw.h
+++ b/source/blender/windowmanager/wm_draw.h
@@ -34,12 +34,8 @@
#include "GPU_glew.h"
-#define USE_TEXTURE_RECTANGLE 1
-
typedef struct wmDrawTriple {
GLuint bind;
- int x, y;
- GLenum target;
} wmDrawTriple;
typedef struct wmDrawData {
diff --git a/source/blender/windowmanager/wm_subwindow.h b/source/blender/windowmanager/wm_subwindow.h
deleted file mode 100644
index cc9abf87514..00000000000
--- a/source/blender/windowmanager/wm_subwindow.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2007 Blender Foundation.
- * All rights reserved.
- *
- *
- * Contributor(s): Blender Foundation
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/windowmanager/wm_subwindow.h
- * \ingroup wm
- */
-
-
-#ifndef __WM_SUBWINDOW_H__
-#define __WM_SUBWINDOW_H__
-
-
-/* *************** internal api ************** */
-void wm_subwindows_free(wmWindow *win);
-
-int wm_subwindow_open(wmWindow *win, const rcti *winrct, bool activate);
-void wm_subwindow_close(wmWindow *win, int swinid);
-int wm_subwindow_get_id(wmWindow *win); /* returns id */
-
-void wm_subwindow_position(wmWindow *win, int swinid, const rcti *winrct, bool activate);
-
-void wm_subwindow_size_get(wmWindow *win, int swinid, int *x, int *y);
-void wm_subwindow_origin_get(wmWindow *win, int swinid, int *x, int *y);
-void wm_subwindow_matrix_get(wmWindow *win, int swinid, float mat[4][4]);
-void wm_subwindow_rect_get(wmWindow *win, int swinid, struct rcti *r_rect);
-void wm_subwindow_rect_set(wmWindow *win, int swinid, const rcti *rect);
-
-#endif /* __WM_SUBWINDOW_H__ */
-
diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h
index 0264955a4c5..b0c7021c496 100644
--- a/source/blender/windowmanager/wm_window.h
+++ b/source/blender/windowmanager/wm_window.h
@@ -58,6 +58,7 @@ void wm_window_process_events (const bContext *C);
void wm_window_process_events_nosleep(void);
void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win);
+void wm_window_reset_drawable(void);
void wm_window_raise (wmWindow *win);
void wm_window_lower (wmWindow *win);
@@ -81,6 +82,7 @@ void wm_window_IME_end (wmWindow *win);
/* *************** window operators ************** */
int wm_window_close_exec(bContext *C, struct wmOperator *op);
int wm_window_fullscreen_toggle_exec(bContext *C, struct wmOperator *op);
+void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win) ATTR_NONNULL();
const struct EnumPropertyItem *wm_window_new_screen_itemf(
bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index 328453df118..60abf0806d3 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -58,8 +58,8 @@ elseif(APPLE)
set(PLAYER_SOURCEINFO ${PLAYER_SOURCEDIR}/Contents/Info.plist)
set_target_properties(blenderplayer PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${PLAYER_SOURCEINFO}
- MACOSX_BUNDLE_SHORT_VERSION_STRING ${BLENDER_VERSION}
- MACOSX_BUNDLE_LONG_VERSION_STRING "${BLENDER_VERSION} ${BLENDER_DATE}")
+ MACOSX_BUNDLE_SHORT_VERSION_STRING "${BLENDER_VERSION}${BLENDER_VERSION_CHAR}"
+ MACOSX_BUNDLE_LONG_VERSION_STRING "${BLENDER_VERSION}${BLENDER_VERSION_CHAR} ${BLENDER_DATE}")
else()
add_executable(blenderplayer bad_level_call_stubs/stubs.c)
@@ -197,10 +197,6 @@ endif()
list(APPEND BLENDER_SORTED_LIBS extern_ceres)
endif()
- if(WITH_MOD_BOOLEAN)
- list(APPEND BLENDER_SORTED_LIBS extern_carve)
- endif()
-
if(WITH_GHOST_XDND)
list(APPEND BLENDER_SORTED_LIBS extern_xdnd)
endif()
diff --git a/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt b/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt
index d2c2129532a..0a50c0876fb 100644
--- a/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt
+++ b/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt
@@ -33,6 +33,7 @@ set(INC
../../blender/blenlib
../../blender/blenkernel
../../blender/blenloader
+ ../../blender/depsgraph
../../blender/makesdna
../../blender/makesrna
../../../intern/glew-mx
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index dca64683833..96242c229d1 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -152,7 +152,6 @@ struct wmManipulatorMap;
#include "../../intern/elbeem/extern/elbeem.h"
#include "../blender/blenkernel/BKE_modifier.h"
#include "../blender/blenkernel/BKE_paint.h"
-#include "../blender/collada/collada.h"
#include "../blender/compositor/COM_compositor.h"
#include "../blender/editors/include/ED_armature.h"
#include "../blender/editors/include/ED_anim_api.h"
@@ -239,10 +238,12 @@ bool BPY_string_is_keyword(const char *str) { return false; }
/* -------------------------------------------------------------------- */
/* Stubs */
+void DRW_deferred_shader_remove(struct GPUMaterial *mat) RET_NONE
+
/*new render funcs */
void EDBM_selectmode_set(struct BMEditMesh *em) RET_NONE
void EDBM_mesh_load(struct Object *ob) RET_NONE
-void EDBM_mesh_make(struct ToolSettings *ts, struct Object *ob, const bool use_key_index) RET_NONE
+void EDBM_mesh_make(struct Object *ob, const int select_mode, const bool use_key_index) RET_NONE
void EDBM_mesh_normals_update(struct BMEditMesh *em) RET_NONE
void *g_system;
bool EDBM_uv_check(struct BMEditMesh *em) RET_ZERO
@@ -265,10 +266,6 @@ struct RenderPass *RE_pass_find_by_name(volatile struct RenderLayer *rl, const c
struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL
bool RE_HasCombinedLayer(RenderResult *res) RET_ZERO
-/* zbuf.c stub */
-void antialias_tagbuf(int xsize, int ysize, char *rectmove) RET_NONE
-void RE_zbuf_accumulate_vecblur(struct NodeBlurData *nbd, int xsize, int ysize, float *newrect, const float *imgrect, float *vecbufrect, const float *zbufrect) RET_NONE
-
/* imagetexture.c stub */
void ibuf_sample(struct ImBuf *ibuf, float fx, float fy, float dx, float dy, float *result) RET_NONE
@@ -281,7 +278,7 @@ int multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], i
int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image) RET_ZERO
int multitex_nodes(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, const short thread, short which_output, struct ShadeInput *shi, struct MTex *mtex, struct ImagePool *pool) RET_ZERO
-struct Material *RE_sample_material_init(struct Material *orig_mat, struct Scene *scene) RET_NULL
+struct Material *RE_sample_material_init(const struct EvaluationContext *eval_ctx, struct Material *orig_mat, struct Scene *scene) RET_NULL
void RE_sample_material_free(struct Material *mat) RET_NONE
void RE_sample_material_color(
struct Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3],
@@ -336,6 +333,10 @@ struct WorkSpace *WM_windows_workspace_get_from_screen(const struct wmWindowMana
struct bScreen *WM_window_get_active_screen(const struct wmWindow *win) RET_NULL
struct Scene *WM_window_get_active_scene(const struct wmWindow *win) RET_NULL
struct WorkSpace *WM_window_get_active_workspace(const wmWindow *win) RET_NULL
+
+struct ViewLayer *WM_window_get_active_view_layer_ex(const struct wmWindow *win, struct Scene **r_scene) RET_NULL
+struct ViewLayer *WM_window_get_active_view_layer(const struct wmWindow *win) RET_NULL
+
void WM_window_change_active_scene(struct Main *bmain, struct bContext *C, struct wmWindow *win, struct Scene *scene_new) RET_NONE
bool WM_window_is_temp_screen(const struct wmWindow *win) RET_ZERO
@@ -481,7 +482,7 @@ void ED_fsmenu_entry_set_path(struct FSMenuEntry *fsentry, const char *name) RET
char *ED_fsmenu_entry_get_name(struct FSMenuEntry *fsentry) RET_NULL
void ED_fsmenu_entry_set_name(struct FSMenuEntry *fsentry, const char *name) RET_NONE
-struct PTCacheEdit *PE_get_current(struct Scene *scene, struct ViewLayer *view_layer, struct Object *ob) RET_NULL
+struct PTCacheEdit *PE_get_current(struct Scene *scene, struct Object *ob) RET_NULL
void PE_current_changed(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob) RET_NONE
/* rna keymap */
@@ -548,18 +549,22 @@ void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_c
void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist) RET_NONE
void ED_view3d_update_viewmat(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4], const struct rcti *rect) RET_NONE
float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit) RET_ZERO
-void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View3D *v3d, struct ScrArea *sa) RET_NONE
+void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa) RET_NONE
void ED_node_shader_default(const struct bContext *C, struct ID *id) RET_NONE
void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh) RET_NONE
struct bScreen *ED_screen_animation_playing(const struct wmWindowManager *wm) RET_NULL
struct Scene *ED_screen_scene_find(const struct bScreen *screen, const struct wmWindowManager *wm) RET_NULL
+struct Scene *ED_screen_scene_find_with_window(const struct bScreen *screen, const struct wmWindowManager *wm, struct wmWindow **r_window) RET_NULL
+struct wmWindow *ED_screen_window_find(const struct bScreen *screen, const struct wmWindowManager *wm) RET_NULL;
bool ED_scene_view_layer_delete(struct Main *bmain, Scene *scene, ViewLayer *layer, ReportList *reports) RET_ZERO
void ED_object_base_select(struct Base *base, eObjectSelect_Mode mode) RET_NONE
+void ED_object_base_activate(struct bContext *C, struct Base *base) RET_NONE
bool ED_object_modifier_remove(struct ReportList *reports, struct Main *bmain, struct Object *ob, struct ModifierData *md) RET_ZERO
struct ModifierData *ED_object_modifier_add(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob, const char *name, int type) RET_ZERO
void ED_object_modifier_clear(struct Main *bmain, struct Object *ob) RET_NONE
void ED_object_editmode_enter(struct bContext *C, int flag) RET_NONE
void ED_object_editmode_exit(struct bContext *C, int flag) RET_NONE
+void ED_object_editmode_exit_ex(struct bContext *C, struct Scene *scene, struct Object *obedit, int flag) RET_NONE
bool ED_object_editmode_load(struct Object *obedit) RET_ZERO
void ED_object_check_force_modifiers(struct Main *bmain, struct Scene *scene, struct Object *object) RET_NONE
bool uiLayoutGetActive(struct uiLayout *layout) RET_ZERO
@@ -601,7 +606,7 @@ int ED_mesh_mirror_spatial_table(struct Object *ob, struct BMEditMesh *em, struc
float ED_rollBoneToVector(EditBone *bone, const float new_up_axis[3], const bool axis_only) RET_ZERO
void ED_space_image_get_size(struct SpaceImage *sima, int *width, int *height) RET_NONE
-bool ED_space_image_check_show_maskedit(struct ViewLayer *view_layer, struct SpaceImage *sima) RET_ZERO
+bool ED_space_image_check_show_maskedit(struct SpaceImage *sima, struct ViewLayer *view_layer) RET_ZERO
bool ED_texture_context_check_world(const struct bContext *C) RET_ZERO
bool ED_texture_context_check_material(const struct bContext *C) RET_ZERO
@@ -626,13 +631,9 @@ bool ED_transform_snap_object_project_ray_ex(
struct Object **r_ob, float r_obmat[4][4]) RET_ZERO
void BIF_selectTransformOrientationValue(struct View3D *v3d, int orientation) RET_NONE
-void ED_lattice_editlatt_make(struct Object *obedit) RET_NONE
-void ED_lattice_editlatt_load(struct Object *obedit) RET_NONE
-
void ED_curve_editnurb_load(struct Object *obedit) RET_NONE
void ED_curve_editnurb_make(struct Object *obedit) RET_NONE
-
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon) RET_NONE
void uiItemFullO(uiLayout *layout, const char *idname, const char *name, int icon, struct IDProperty *properties, int context, int flag, struct PointerRNA *r_opptr) RET_NONE
@@ -675,6 +676,7 @@ void UI_GetThemeColorBlendShade3fv(int colorid1, int colorid2, float fac, int of
void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4]) RET_NONE
void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned char col[3]) RET_NONE
void UI_GetThemeColorShadeAlpha4ubv(int colorid, int coloffset, int alphaoffset, unsigned char col[4]) RET_NONE
+void UI_widgetbase_draw_cache_flush(void) RET_NONE
/* rna template */
void uiTemplateAnyID(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *proptypename, const char *text) RET_NONE
@@ -763,16 +765,14 @@ void RE_engine_update_memory_stats(struct RenderEngine *engine, float mem_used,
struct RenderEngine *RE_engine_create(struct RenderEngineType *type) RET_NULL
void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe) RET_NONE
void RE_FreePersistentData(void) RET_NONE
-void RE_point_density_cache(struct Scene *scene, struct ViewLayer *view_layer, struct PointDensity *pd, const bool use_render_params) RET_NONE
-void RE_point_density_minmax(struct Scene *scene, struct ViewLayer *view_layer, struct PointDensity *pd, const bool use_render_params, float r_min[3], float r_max[3]) RET_NONE
-void RE_point_density_sample(struct Scene *scene, struct ViewLayer *view_layer, struct PointDensity *pd, const int resolution, const bool use_render_params, float *values) RET_NONE
+void RE_point_density_cache(const struct EvaluationContext *eval_ctx, struct PointDensity *pd) RET_NONE
+void RE_point_density_minmax(const struct EvaluationContext *eval_ctx, struct PointDensity *pd, float r_min[3], float r_max[3]) RET_NONE
+void RE_point_density_sample(const struct EvaluationContext *eval_ctx, struct PointDensity *pd, const int resolution, float *values) RET_NONE
void RE_point_density_free(struct PointDensity *pd) RET_NONE
-void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]) RET_NONE
+void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *random, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]) RET_NONE
void RE_FreeAllPersistentData(void) RET_NONE
float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta) RET_ZERO
void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer, const char *name, int channels, const char *chanid, int type) RET_NONE
-struct ViewLayer *RE_engine_get_view_layer(struct Render *re) RET_NULL
-void RE_SetDepsgraph(struct Render *re, struct Depsgraph *graph) RET_NONE
/* Draw */
void OBJECT_collection_settings_create(struct IDProperty *properties) RET_NONE
@@ -821,33 +821,6 @@ struct uiLayout *uiLayoutRadial(struct uiLayout *layout) RET_NULL
int UI_pie_menu_invoke_from_operator_enum(struct bContext *C, const char *title, const char *opname,
const char *propname, const struct wmEvent *event) RET_ZERO
-/* RNA COLLADA dependency */
-int collada_export(const struct EvaluationContext *eval_ctx,
- struct Scene *sce,
- struct ViewLayer *view_layer,
- const char *filepath,
- int apply_modifiers,
- BC_export_mesh_type export_mesh_type,
-
- int selected,
- int include_children,
- int include_armatures,
- int include_shapekeys,
- int deform_bones_only,
-
- int active_uv_only,
- int include_material_textures,
- int use_texture_copies,
-
- int triangulate,
- int use_object_instantiation,
- int use_blender_profile,
- int sort_by_name,
- BC_export_transformation_type export_transformation_type,
- int open_sim,
- int limit_precision,
- int keep_bind_info) RET_ZERO
-
void ED_mesh_calc_tessface(struct Mesh *mesh, bool free_mpoly) RET_NONE
/* bpy/python internal api */
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index c5acd7e640e..1adef28f2c8 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -26,6 +26,7 @@
setup_libdirs()
blender_include_dirs(
+ ../../intern/clog
../../intern/guardedalloc
../../intern/glew-mx
../blender/blenlib
@@ -870,8 +871,8 @@ elseif(APPLE)
set_target_properties(blender PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${OSX_APP_SOURCEDIR}/Contents/Info.plist
- MACOSX_BUNDLE_SHORT_VERSION_STRING ${BLENDER_VERSION}
- MACOSX_BUNDLE_LONG_VERSION_STRING "${BLENDER_VERSION} ${BLENDER_DATE}")
+ MACOSX_BUNDLE_SHORT_VERSION_STRING "${BLENDER_VERSION}${BLENDER_VERSION_CHAR}"
+ MACOSX_BUNDLE_LONG_VERSION_STRING "${BLENDER_VERSION}${BLENDER_VERSION_CHAR} ${BLENDER_DATE}")
# Gather the date in finder-style
execute_process(COMMAND date "+%m/%d/%Y/%H:%M"
@@ -1030,70 +1031,4 @@ if(WIN32 AND NOT WITH_PYTHON_MODULE)
COMPONENT Blender
DESTINATION "."
)
- if(CMAKE_CL_64)
- set(_WIN_PLATFORM x64)
- else()
- set(_WIN_PLATFORM x86)
- endif()
- if(MSVC12_REDIST_DIR)
- install(
- FILES
- ${MSVC12_REDIST_DIR}/${_WIN_PLATFORM}/Microsoft.VC120.CRT/msvcp120.dll
- ${MSVC12_REDIST_DIR}/${_WIN_PLATFORM}/Microsoft.VC120.CRT/msvcr120.dll
- DESTINATION "."
- )
- if(WITH_OPENMP)
- install(
- FILES ${MSVC12_REDIST_DIR}/${_WIN_PLATFORM}/Microsoft.VC120.OpenMP/vcomp120.dll
- DESTINATION "."
- )
- endif()
- endif()
-
- if(MSVC14_REDIST_DIR)
- set(KITSDIRx86 "$ENV{${ProgramFilesX86_NAME}}/Windows Kits/10/")
- set(KITSDIR "$ENV{ProgramFiles}/Windows Kits/10/")
- if(IS_DIRECTORY ${KITSDIR})
- set(KITSPATH "${KITSDIR}/Redist/ucrt/DLLs/${_WIN_PLATFORM}")
- else()
- if(IS_DIRECTORY ${KITSDIRx86})
- set(KITSPATH "${KITSDIRx86}/Redist/ucrt/DLLs/${_WIN_PLATFORM}")
- else()
- message(FATAL_ERROR "Windows 10 SDK directory not found")
- endif()
- endif()
- FILE(TO_CMAKE_PATH ${KITSPATH} KITSPATH)
- install(
- FILES
- ${KITSPATH}/api-ms-win-core-file-l1-2-0.dll
- ${KITSPATH}/api-ms-win-core-file-l2-1-0.dll
- ${KITSPATH}/api-ms-win-core-localization-l1-2-0.dll
- ${KITSPATH}/api-ms-win-core-processthreads-l1-1-0.dll
- ${KITSPATH}/api-ms-win-core-processthreads-l1-1-1.dll
- ${KITSPATH}/api-ms-win-core-synch-l1-1-0.dll
- ${KITSPATH}/api-ms-win-core-synch-l1-2-0.dll
- ${KITSPATH}/api-ms-win-core-timezone-l1-1-0.dll
- ${KITSPATH}/api-ms-win-crt-conio-l1-1-0.dll
- ${KITSPATH}/api-ms-win-crt-convert-l1-1-0.dll
- ${KITSPATH}/api-ms-win-crt-environment-l1-1-0.dll
- ${KITSPATH}/api-ms-win-crt-filesystem-l1-1-0.dll
- ${KITSPATH}/api-ms-win-crt-heap-l1-1-0.dll
- ${KITSPATH}/api-ms-win-crt-locale-l1-1-0.dll
- ${KITSPATH}/api-ms-win-crt-math-l1-1-0.dll
- ${KITSPATH}/api-ms-win-crt-process-l1-1-0.dll
- ${KITSPATH}/api-ms-win-crt-runtime-l1-1-0.dll
- ${KITSPATH}/api-ms-win-crt-stdio-l1-1-0.dll
- ${KITSPATH}/api-ms-win-crt-string-l1-1-0.dll
- ${KITSPATH}/api-ms-win-crt-time-l1-1-0.dll
- ${KITSPATH}/ucrtbase.dll
- ${MSVC14_REDIST_DIR}/${_WIN_PLATFORM}/Microsoft.VC140.CRT/vcruntime140.dll
- DESTINATION "."
- )
- if(WITH_OPENMP)
- install(
- FILES ${MSVC14_REDIST_DIR}/${_WIN_PLATFORM}/Microsoft.VC140.OpenMP/vcomp140.dll
- DESTINATION "."
- )
- endif()
- endif()
endif()
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 78bab14cd96..2aa60c3e2a7 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -42,6 +42,8 @@
#include "MEM_guardedalloc.h"
+#include "CLG_log.h"
+
#include "DNA_genfile.h"
#include "BLI_args.h"
@@ -49,6 +51,7 @@
#include "BLI_utildefines.h"
#include "BLI_callbacks.h"
#include "BLI_string.h"
+#include "BLI_system.h"
/* mostly init functions */
#include "BKE_appdir.h"
@@ -180,6 +183,11 @@ static void callback_main_atexit(void *user_data)
#endif
}
+static void callback_clg_fatal(void *fp)
+{
+ BLI_system_backtrace(fp);
+}
+
/** \} */
@@ -304,6 +312,10 @@ int main(
sdlewInit();
#endif
+ /* Initialize logging */
+ CLG_init();
+ CLG_fatal_fn_set(callback_clg_fatal);
+
C = CTX_create();
#ifdef WITH_PYTHON_MODULE
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index 6b47d7c3474..dac22322361 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -30,6 +30,8 @@
#include "MEM_guardedalloc.h"
+#include "CLG_log.h"
+
#ifdef WIN32
# include "BLI_winstuff.h"
#endif
@@ -428,26 +430,6 @@ static void arg_py_context_restore(
/** \} */
-static void render_set_depgraph(bContext *C, Render *re)
-{
- /* TODO(sergey): For until we make depsgraph to be created and
- * handled by render pipeline.
- */
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- /* NOTE: This is STUPID to use first layer, but is ok for now
- * (at least for until depsgraph becomes per-layer).
- * Apparently, CTX_data_layer is crashing here (context's layer
- * is NULL for old files, and there is no workspace).
- */
- ViewLayer *view_layer = scene->view_layers.first;
- Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
- DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
- DEG_graph_on_visible_update(bmain, depsgraph);
-
- RE_SetDepsgraph(re, depsgraph);
-}
-
/* -------------------------------------------------------------------- */
/** \name Handle Argument Callbacks
@@ -524,7 +506,7 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo
printf("\n");
printf("Window Options:\n");
BLI_argsPrintArgDoc(ba, "--window-border");
- BLI_argsPrintArgDoc(ba, "--window-borderless");
+ BLI_argsPrintArgDoc(ba, "--window-fullscreen");
BLI_argsPrintArgDoc(ba, "--window-geometry");
BLI_argsPrintArgDoc(ba, "--start-console");
BLI_argsPrintArgDoc(ba, "--no-native-pixels");
@@ -548,6 +530,12 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo
BLI_argsPrintArgDoc(ba, "--python-exit-code");
BLI_argsPrintArgDoc(ba, "--addons");
+ printf("\n");
+ printf("Logging Options:\n");
+ BLI_argsPrintArgDoc(ba, "--log");
+ BLI_argsPrintArgDoc(ba, "--log-level");
+ BLI_argsPrintArgDoc(ba, "--log-show-basename");
+ BLI_argsPrintArgDoc(ba, "--log-file");
printf("\n");
printf("Debug Options:\n");
@@ -570,6 +558,9 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo
BLI_argsPrintArgDoc(ba, "--debug-jobs");
BLI_argsPrintArgDoc(ba, "--debug-python");
BLI_argsPrintArgDoc(ba, "--debug-depsgraph");
+ BLI_argsPrintArgDoc(ba, "--debug-depsgraph-eval");
+ BLI_argsPrintArgDoc(ba, "--debug-depsgraph-build");
+ BLI_argsPrintArgDoc(ba, "--debug-depsgraph-tag");
BLI_argsPrintArgDoc(ba, "--debug-depsgraph-no-threads");
BLI_argsPrintArgDoc(ba, "--debug-gpumem");
@@ -719,6 +710,112 @@ static int arg_handle_background_mode_set(int UNUSED(argc), const char **UNUSED(
return 0;
}
+static const char arg_handle_log_level_set_doc[] =
+"<level>\n"
+"\n"
+"\tSet the logging verbosity level (higher for more details) defaults to 1, use -1 to log all levels."
+;
+static int arg_handle_log_level_set(int argc, const char **argv, void *UNUSED(data))
+{
+ const char *arg_id = "--log-level";
+ if (argc > 1) {
+ const char *err_msg = NULL;
+ if (!parse_int_clamp(argv[1], NULL, -1, INT_MAX, &G.log.level, &err_msg)) {
+ printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
+ }
+ if (G.log.level == -1) {
+ G.log.level = INT_MAX;
+ }
+ return 1;
+ }
+ else {
+ printf("\nError: '%s' no args given.\n", arg_id);
+ return 0;
+ }
+}
+
+static const char arg_handle_log_show_basename_set_doc[] =
+"\n\tOnly show file name in output (not the leading path)."
+;
+static int arg_handle_log_show_basename_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
+{
+ CLG_output_use_basename_set(true);
+ return 0;
+}
+
+static const char arg_handle_log_file_set_doc[] =
+"<filename>\n"
+"\n"
+"\tSet a file to output the log to."
+;
+static int arg_handle_log_file_set(int argc, const char **argv, void *UNUSED(data))
+{
+ const char *arg_id = "--log-file";
+ if (argc > 1) {
+ errno = 0;
+ FILE *fp = BLI_fopen(argv[1], "w");
+ if (fp == NULL) {
+ const char *err_msg = errno ? strerror(errno) : "unknown";
+ printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
+ }
+ else {
+ if (UNLIKELY(G.log.file != NULL)) {
+ fclose(G.log.file);
+ }
+ G.log.file = fp;
+ CLG_output_set(G.log.file);
+ }
+ return 1;
+ }
+ else {
+ printf("\nError: '%s' no args given.\n", arg_id);
+ return 0;
+ }
+}
+
+static const char arg_handle_log_set_doc[] =
+"<match>\n"
+"\tEnable logging categories, taking a single comma separated argument.\n"
+"\tMultiple categories can be matched using a '.*' suffix,\n"
+"\tso '--log \"wm.*\"' logs every kind of window-manager message.\n"
+"\tUse \"^\" prefix to ignore, so '--log \"*,^wm.operator.*\"' logs all except for 'wm.operators.*'\n"
+"\tUse \"*\" to log everything."
+;
+static int arg_handle_log_set(int argc, const char **argv, void *UNUSED(data))
+{
+ const char *arg_id = "--log";
+ if (argc > 1) {
+ const char *str_step = argv[1];
+ while (*str_step) {
+ const char *str_step_end = strchr(str_step, ',');
+ int str_step_len = str_step_end ? (str_step_end - str_step) : strlen(str_step);
+
+ if (str_step[0] == '^') {
+ CLG_type_filter_exclude(str_step + 1, str_step_len - 1);
+ }
+ else {
+ CLG_type_filter_include(str_step, str_step_len);
+ }
+
+ if (str_step_end) {
+ /* typically only be one, but don't fail on multiple.*/
+ while (*str_step_end == ',') {
+ str_step_end++;
+ }
+ str_step = str_step_end;
+ }
+ else {
+ break;
+ }
+ }
+ return 1;
+ }
+ else {
+ printf("\nError: '%s' no args given.\n", arg_id);
+ return 0;
+ }
+}
+
static const char arg_handle_debug_mode_set_doc[] =
"\n"
"\tTurn debugging on.\n"
@@ -765,9 +862,19 @@ static const char arg_handle_debug_mode_generic_set_doc_jobs[] =
static const char arg_handle_debug_mode_generic_set_doc_gpu[] =
"\n\tEnable gpu debug context and information for OpenGL 4.3+.";
static const char arg_handle_debug_mode_generic_set_doc_depsgraph[] =
-"\n\tEnable debug messages from dependency graph.";
+"\n\tEnable all debug messages from dependency graph.";
+static const char arg_handle_debug_mode_generic_set_doc_depsgraph_build[] =
+"\n\tEnable debug messages from dependency graph related on graph construction.";
+static const char arg_handle_debug_mode_generic_set_doc_depsgraph_tag[] =
+"\n\tEnable debug messages from dependency graph related on tagging.";
+static const char arg_handle_debug_mode_generic_set_doc_depsgraph_time[] =
+"\n\tEnable debug messages from dependency graph related on timing.";
+static const char arg_handle_debug_mode_generic_set_doc_depsgraph_eval[] =
+"\n\tEnable debug messages from dependency graph related on evaluation.";
static const char arg_handle_debug_mode_generic_set_doc_depsgraph_no_threads[] =
"\n\tSwitch dependency graph to a single threaded evaluation.";
+static const char arg_handle_debug_mode_generic_set_doc_depsgraph_pretty[] =
+"\n\tEnable colors for dependency graph debug messages.";
static const char arg_handle_debug_mode_generic_set_doc_gpumem[] =
"\n\tEnable GPU memory stats in status bar.";
@@ -981,7 +1088,7 @@ static int arg_handle_with_borders(int UNUSED(argc), const char **UNUSED(argv),
}
static const char arg_handle_without_borders_doc[] =
-"\n\tForce opening without borders."
+"\n\tForce opening in fullscreen mode."
;
static int arg_handle_without_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
{
@@ -1348,7 +1455,7 @@ static const char arg_handle_render_frame_doc[] =
"\n"
"\t* +<frame> start frame relative, -<frame> end frame relative.\n"
"\t* A comma separated list of frames can also be used (no spaces).\n"
-"\t* A range of frames can be expressed using '..' seperator between the first and last frames (inclusive).\n"
+"\t* A range of frames can be expressed using '..' separator between the first and last frames (inclusive).\n"
;
static int arg_handle_render_frame(int argc, const char **argv, void *data)
{
@@ -1373,10 +1480,9 @@ static int arg_handle_render_frame(int argc, const char **argv, void *data)
}
re = RE_NewSceneRender(scene);
- BLI_begin_threaded_malloc();
+ BLI_threaded_malloc_begin();
BKE_reports_init(&reports, RPT_STORE);
RE_SetReports(re, &reports);
- render_set_depgraph(C, re);
for (int i = 0; i < frames_range_len; i++) {
/* We could pass in frame ranges,
* but prefer having exact behavior as passing in multiple frames */
@@ -1390,7 +1496,7 @@ static int arg_handle_render_frame(int argc, const char **argv, void *data)
}
RE_SetReports(re, NULL);
BKE_reports_clear(&reports);
- BLI_end_threaded_malloc();
+ BLI_threaded_malloc_end();
MEM_freeN(frame_range_arr);
return 1;
}
@@ -1416,14 +1522,13 @@ static int arg_handle_render_animation(int UNUSED(argc), const char **UNUSED(arg
Main *bmain = CTX_data_main(C);
Render *re = RE_NewSceneRender(scene);
ReportList reports;
- BLI_begin_threaded_malloc();
+ BLI_threaded_malloc_begin();
BKE_reports_init(&reports, RPT_STORE);
RE_SetReports(re, &reports);
- render_set_depgraph(C, re);
RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, scene->r.sfra, scene->r.efra, scene->r.frame_step);
RE_SetReports(re, NULL);
BKE_reports_clear(&reports);
- BLI_end_threaded_malloc();
+ BLI_threaded_malloc_end();
}
else {
printf("\nError: no blend loaded. cannot use '-a'.\n");
@@ -1666,7 +1771,7 @@ static int arg_handle_python_console_run(int UNUSED(argc), const char **argv, vo
}
static const char arg_handle_python_exit_code_set_doc[] =
-"\n"
+"<code>\n"
"\tSet the exit-code in [0..255] to exit if a Python exception is raised\n"
"\t(only for scripts executed from the command line), zero disables."
;
@@ -1692,7 +1797,8 @@ static int arg_handle_python_exit_code_set(int argc, const char **argv, void *UN
}
static const char arg_handle_addons_set_doc[] =
-"\n\tComma separated list of add-ons (no spaces)."
+"<addon(s)>\n"
+"\tComma separated list of add-ons (no spaces)."
;
static int arg_handle_addons_set(int argc, const char **argv, void *data)
{
@@ -1812,6 +1918,11 @@ void main_args_setup(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
BLI_argsAdd(ba, 1, "-a", NULL, CB(arg_handle_playback_mode), NULL);
+ BLI_argsAdd(ba, 1, NULL, "--log", CB(arg_handle_log_set), ba);
+ BLI_argsAdd(ba, 1, NULL, "--log-level", CB(arg_handle_log_level_set), ba);
+ BLI_argsAdd(ba, 1, NULL, "--log-show-basename", CB(arg_handle_log_show_basename_set), ba);
+ BLI_argsAdd(ba, 1, NULL, "--log-file", CB(arg_handle_log_file_set), ba);
+
BLI_argsAdd(ba, 1, "-d", "--debug", CB(arg_handle_debug_mode_set), ba);
#ifdef WITH_FFMPEG
@@ -1855,8 +1966,18 @@ void main_args_setup(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
CB_EX(arg_handle_debug_mode_generic_set, gpu), (void *)G_DEBUG_GPU);
BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph",
CB_EX(arg_handle_debug_mode_generic_set, depsgraph), (void *)G_DEBUG_DEPSGRAPH);
+ BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-build",
+ CB_EX(arg_handle_debug_mode_generic_set, depsgraph_build), (void *)G_DEBUG_DEPSGRAPH_BUILD);
+ BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-eval",
+ CB_EX(arg_handle_debug_mode_generic_set, depsgraph_eval), (void *)G_DEBUG_DEPSGRAPH_EVAL);
+ BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-tag",
+ CB_EX(arg_handle_debug_mode_generic_set, depsgraph_tag), (void *)G_DEBUG_DEPSGRAPH_TAG);
+ BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-time",
+ CB_EX(arg_handle_debug_mode_generic_set, depsgraph_time), (void *)G_DEBUG_DEPSGRAPH_TIME);
BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-no-threads",
CB_EX(arg_handle_debug_mode_generic_set, depsgraph_no_threads), (void *)G_DEBUG_DEPSGRAPH_NO_THREADS);
+ BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-pretty",
+ CB_EX(arg_handle_debug_mode_generic_set, depsgraph_pretty), (void *)G_DEBUG_DEPSGRAPH_PRETTY);
BLI_argsAdd(ba, 1, NULL, "--debug-gpumem",
CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_MEM);
BLI_argsAdd(ba, 1, NULL, "--debug-gpu-shaders",
@@ -1876,7 +1997,7 @@ void main_args_setup(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
/* second pass: custom window stuff */
BLI_argsAdd(ba, 2, "-p", "--window-geometry", CB(arg_handle_window_geometry), NULL);
BLI_argsAdd(ba, 2, "-w", "--window-border", CB(arg_handle_with_borders), NULL);
- BLI_argsAdd(ba, 2, "-W", "--window-borderless", CB(arg_handle_without_borders), NULL);
+ BLI_argsAdd(ba, 2, "-W", "--window-fullscreen", CB(arg_handle_without_borders), NULL);
BLI_argsAdd(ba, 2, "-con", "--start-console", CB(arg_handle_start_with_console), NULL);
BLI_argsAdd(ba, 2, "-R", NULL, CB(arg_handle_register_extension), NULL);
BLI_argsAdd(ba, 2, "-r", NULL, CB_EX(arg_handle_register_extension, silent), ba);
diff --git a/source/creator/creator_signals.c b/source/creator/creator_signals.c
index 81e6178c502..feb108da289 100644
--- a/source/creator/creator_signals.c
+++ b/source/creator/creator_signals.c
@@ -64,6 +64,7 @@
#include "BKE_main.h"
#include "BKE_report.h"
+
/* for passing information between creator and gameengine */
#ifdef WITH_GAMEENGINE
# include "BL_System.h"
@@ -75,6 +76,12 @@
#include "creator_intern.h" /* own include */
+// #define USE_WRITE_CRASH_BLEND
+#ifdef USE_WRITE_CRASH_BLEND
+# include "BKE_undo_system.h"
+# include "BLO_undofile.h"
+#endif
+
/* set breakpoints here when running in debug mode, useful to catch floating point errors */
#if defined(__linux__) || defined(_WIN32) || defined(OSX_SSE_FPE)
static void sig_handle_fpe(int UNUSED(sig))
@@ -110,29 +117,32 @@ static void sig_handle_crash_backtrace(FILE *fp)
static void sig_handle_crash(int signum)
{
+ wmWindowManager *wm = G.main->wm.first;
-#if 0
- {
- char fname[FILE_MAX];
+#ifdef USE_WRITE_CRASH_BLEND
+ if (wm->undo_stack) {
+ struct MemFile *memfile = BKE_undosys_stack_memfile_get_active(wm->undo_stack);
+ if (memfile) {
+ char fname[FILE_MAX];
- if (!G.main->name[0]) {
- BLI_make_file_string("/", fname, BKE_tempdir_base(), "crash.blend");
- }
- else {
- BLI_strncpy(fname, G.main->name, sizeof(fname));
- BLI_replace_extension(fname, sizeof(fname), ".crash.blend");
- }
+ if (!G.main->name[0]) {
+ BLI_make_file_string("/", fname, BKE_tempdir_base(), "crash.blend");
+ }
+ else {
+ BLI_strncpy(fname, G.main->name, sizeof(fname));
+ BLI_replace_extension(fname, sizeof(fname), ".crash.blend");
+ }
- printf("Writing: %s\n", fname);
- fflush(stdout);
+ printf("Writing: %s\n", fname);
+ fflush(stdout);
- BKE_undo_save_file(fname);
+ BLO_memfile_write_file(memfile, fname);
+ }
}
#endif
FILE *fp;
char header[512];
- wmWindowManager *wm = G.main->wm.first;
char fname[FILE_MAX];
@@ -338,4 +348,4 @@ void main_signal_setup_fpe(void)
#endif
}
-#endif /* WITH_PYTHON_MODULE */ \ No newline at end of file
+#endif /* WITH_PYTHON_MODULE */
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index acd425e788a..39f517e03e8 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -132,7 +132,7 @@
#include "DNA_key_types.h"
#include "DNA_armature_types.h"
#include "DNA_action_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_constraint_types.h"
#include "MEM_guardedalloc.h"
@@ -1541,7 +1541,7 @@ static KX_GameObject *gameobject_from_blenderobject(
gameobj->AddMesh(meshobj);
// gather levels of detail
- if (BLI_listbase_count_ex(&ob->lodlevels, 2) > 1) {
+ if (BLI_listbase_count_at_most(&ob->lodlevels, 2) > 1) {
LodLevel *lod = ((LodLevel*)ob->lodlevels.first)->next;
Mesh* lodmesh = mesh;
Object* lodmatob = ob;
@@ -1688,6 +1688,7 @@ struct parentChildLink {
SG_Node* m_gamechildnode;
};
+#if 0
static bPoseChannel *get_active_posechannel2(Object *ob)
{
bArmature *arm= (bArmature*)ob->data;
@@ -1701,6 +1702,7 @@ static bPoseChannel *get_active_posechannel2(Object *ob)
return NULL;
}
+#endif
static ListBase *get_active_constraints2(Object *ob)
{
@@ -1708,6 +1710,7 @@ static ListBase *get_active_constraints2(Object *ob)
return NULL;
// XXX - shouldnt we care about the pose data and not the mode???
+#if 0
if (ob->mode & OB_MODE_POSE) {
bPoseChannel *pchan;
@@ -1715,8 +1718,11 @@ static ListBase *get_active_constraints2(Object *ob)
if (pchan)
return &pchan->constraints;
}
- else
+ else
+#endif
+ {
return &ob->constraints;
+ }
return NULL;
}
@@ -2053,7 +2059,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
for (git=tempglist.begin(); git!=tempglist.end(); git++)
{
Group* group = *git;
- FOREACH_GROUP_OBJECT(group, blenderobject)
+ FOREACH_GROUP_OBJECT_BEGIN(group, blenderobject)
{
if (converter->FindGameObject(blenderobject) == NULL)
{
@@ -2089,7 +2095,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
}
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
}
}
diff --git a/source/gameengine/Ketsji/KX_FontObject.cpp b/source/gameengine/Ketsji/KX_FontObject.cpp
index 91e8e4fd42b..ae79284288d 100644
--- a/source/gameengine/Ketsji/KX_FontObject.cpp
+++ b/source/gameengine/Ketsji/KX_FontObject.cpp
@@ -142,7 +142,7 @@ int GetFontId(VFont *vfont)
fontid = BLF_load("default");
/* XXX the following code is supposed to work (after you add get_builtin_packedfile to BKE_font.h )
- * unfortunately it's crashing on blf_glyph.c:173 because gc->max_glyph_width is 0
+ * unfortunately it's crashing on blf_glyph.c:173 because gc->glyph_width_max is 0
*/
// packedfile=get_builtin_packedfile();
// fontid= BLF_load_mem(font->name, (unsigned char*)packedfile->data, packedfile->size);
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 48b50d24975..0e6b04c6df5 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -738,7 +738,7 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
m_groupGameObjects.clear();
group = blgroupobj->dup_group;
- FOREACH_GROUP_BASE(group, base)
+ FOREACH_GROUP_BASE_BEGIN(group, base)
{
Object *blenderobj = base->object;
if (blgroupobj == blenderobj)
@@ -761,7 +761,7 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
}
m_groupGameObjects.insert(gameobj);
}
- FOREACH_GROUP_BASE_END
+ FOREACH_GROUP_BASE_END;
set<CValue*>::iterator oit;
for (oit=m_groupGameObjects.begin(); oit != m_groupGameObjects.end(); oit++)
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index 72c96668fe7..78d2d88cc65 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -49,7 +49,7 @@ subject to the following restrictions:
#include "DNA_scene_types.h"
#include "DNA_world_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
extern "C" {
#include "BLI_utildefines.h"
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
index 083e9e28502..11ec97ca5f8 100644
--- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp
+++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
@@ -228,7 +228,7 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV
codecCtx->frame_rate_base=1000;
m_baseFrameRate = (double)codecCtx->frame_rate / (double)codecCtx->frame_rate_base;
#else
- m_baseFrameRate = av_q2d(av_get_r_frame_rate_compat(formatCtx->streams[videoStream]));
+ m_baseFrameRate = av_q2d(av_get_r_frame_rate_compat(formatCtx, formatCtx->streams[videoStream]));
#endif
if (m_baseFrameRate <= 0.0)
m_baseFrameRate = defFrameRate;
@@ -467,8 +467,8 @@ bool VideoFFmpeg::startCache()
CachePacket *packet = new CachePacket();
BLI_addtail(&m_packetCacheFree, packet);
}
- BLI_init_threads(&m_thread, cacheThread, 1);
- BLI_insert_thread(&m_thread, this);
+ BLI_threadpool_init(&m_thread, cacheThread, 1);
+ BLI_threadpool_insert(&m_thread, this);
m_cacheStarted = true;
}
return m_cacheStarted;
@@ -479,7 +479,7 @@ void VideoFFmpeg::stopCache()
if (m_cacheStarted)
{
m_stopThread = true;
- BLI_end_threads(&m_thread);
+ BLI_threadpool_end(&m_thread);
// now delete the cache
CacheFrame *frame;
CachePacket *packet;
diff --git a/source/tools b/source/tools
-Subproject ccf20e08702ee6424edbda01544bb9f8bc386de
+Subproject 7695e14cfc5820ac66546e0e515914d85ab81af